WaveOut: correct variable naming, style updates
Adopt Google C++ style guide naming: m_hWaveOut → wave_out_handle m_hSoundEvent → sound_event_handle m_aBuffers → buffers m_iSampleRate → sample_rate m_bShutdown → shutdown m_iLastCursorPos → last_cursor_pos b_InitSuccess → init_success NUM_CHUNKS → num_blocks BUFFERSIZE_FRAMES → num_frames_per_block CHUNKSIZE → block_size I've also fixed spacing in the constructor and reorganized the list of member variables in the header for easier reading, and added context to the comment in the header file, changed a static const int to constexpr int, etc s
This commit is contained in:
@@ -27,21 +27,15 @@ namespace {
|
|||||||
// To achieve this, we use 512 frames per block and determine the number
|
// To achieve this, we use 512 frames per block and determine the number
|
||||||
// of blocks and buffer size in frames based on the sample rate.
|
// of blocks and buffer size in frames based on the sample rate.
|
||||||
constexpr int kTargetLatency = 118;
|
constexpr int kTargetLatency = 118;
|
||||||
|
constexpr int kChannels = 2;
|
||||||
// CHANNELS should be renamed CHANNELS
|
constexpr int kBlockSizeFrames = 512;
|
||||||
constexpr int CHANNELS = 2;
|
constexpr int kBytesPerFrame = kChannels * 2; // 16 bit
|
||||||
|
|
||||||
// CHUNKSIZE_FRAMES should be renamed kBlockSizeFrames
|
|
||||||
constexpr int CHUNKSIZE_FRAMES = 512;
|
|
||||||
|
|
||||||
// BYTES_PER_FRAME should be renamed kBytesPerFrame
|
|
||||||
constexpr int BYTES_PER_FRAME = CHANNELS * 2; // 16 bit
|
|
||||||
|
|
||||||
inline int CalculateNumBlocks( int sampleRate )
|
inline int CalculateNumBlocks( int sampleRate )
|
||||||
{
|
{
|
||||||
return (sampleRate * kTargetLatency +
|
return (sampleRate * kTargetLatency +
|
||||||
(1000 * CHUNKSIZE_FRAMES - 1)) /
|
(1000 * kBlockSizeFrames - 1)) /
|
||||||
(1000 * CHUNKSIZE_FRAMES);
|
(1000 * kBlockSizeFrames);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -69,42 +63,42 @@ void RageSoundDriver_WaveOut::MixerThread()
|
|||||||
if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) )
|
if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) )
|
||||||
LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set sound thread priority") );
|
LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set sound thread priority") );
|
||||||
|
|
||||||
while( !m_bShutdown )
|
while( !wo_shutdown_ )
|
||||||
{
|
{
|
||||||
while( GetData() )
|
while( GetData() )
|
||||||
;
|
;
|
||||||
|
|
||||||
WaitForSingleObject( m_hSoundEvent, 10 );
|
WaitForSingleObject( soundevent_handle_, 10 );
|
||||||
}
|
}
|
||||||
|
|
||||||
waveOutReset( m_hWaveOut );
|
waveOutReset( waveout_handle_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RageSoundDriver_WaveOut::GetData()
|
bool RageSoundDriver_WaveOut::GetData()
|
||||||
{
|
{
|
||||||
/* Look for a free buffer. */
|
/* Look for a free buffer. */
|
||||||
int b;
|
int b;
|
||||||
for( b = 0; b < NUM_CHUNKS; ++b )
|
for( b = 0; b < wo_num_blocks_; ++b )
|
||||||
if( m_aBuffers[b].dwFlags & WHDR_DONE )
|
if( wo_buffers_[b].dwFlags & WHDR_DONE )
|
||||||
break;
|
break;
|
||||||
if( b == NUM_CHUNKS )
|
if( b == wo_num_blocks_ )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Call the callback. */
|
/* Call the callback. */
|
||||||
this->Mix( (int16_t *) m_aBuffers[b].lpData, CHUNKSIZE_FRAMES, m_iLastCursorPos, GetPosition() );
|
this->Mix( (int16_t *) wo_buffers_[b].lpData, kBlockSizeFrames, wo_last_cursor_position_, GetPosition() );
|
||||||
|
|
||||||
MMRESULT ret = waveOutWrite( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
MMRESULT ret = waveOutWrite( waveout_handle_, &wo_buffers_[b], sizeof(wo_buffers_[b]) );
|
||||||
if( ret != MMSYSERR_NOERROR )
|
if( ret != MMSYSERR_NOERROR )
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
if (b_InitSuccess == false)
|
if (wo_init_success_ == false)
|
||||||
{
|
{
|
||||||
FAIL_M(wo_ssprintf(ret, "waveOutWrite failed"));
|
FAIL_M(wo_ssprintf(ret, "waveOutWrite failed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment m_iLastCursorPos. */
|
/* Increment wo_last_cursor_position_. */
|
||||||
m_iLastCursorPos += CHUNKSIZE_FRAMES;
|
wo_last_cursor_position_ += kBlockSizeFrames;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -119,7 +113,7 @@ int64_t RageSoundDriver_WaveOut::GetPosition() const
|
|||||||
{
|
{
|
||||||
MMTIME tm;
|
MMTIME tm;
|
||||||
tm.wType = TIME_SAMPLES;
|
tm.wType = TIME_SAMPLES;
|
||||||
MMRESULT ret = waveOutGetPosition( m_hWaveOut, &tm, sizeof(tm) );
|
MMRESULT ret = waveOutGetPosition( waveout_handle_, &tm, sizeof(tm) );
|
||||||
if( ret != MMSYSERR_NOERROR )
|
if( ret != MMSYSERR_NOERROR )
|
||||||
FAIL_M( wo_ssprintf(ret, "waveOutGetPosition failed") );
|
FAIL_M( wo_ssprintf(ret, "waveOutGetPosition failed") );
|
||||||
|
|
||||||
@@ -127,39 +121,39 @@ int64_t RageSoundDriver_WaveOut::GetPosition() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
RageSoundDriver_WaveOut::RageSoundDriver_WaveOut()
|
RageSoundDriver_WaveOut::RageSoundDriver_WaveOut()
|
||||||
: m_hWaveOut(nullptr)
|
: MixingThread()
|
||||||
, m_hSoundEvent(CreateEvent(nullptr, false, true, nullptr))
|
, waveout_handle_(nullptr)
|
||||||
, m_iLastCursorPos(0)
|
, soundevent_handle_(CreateEvent(nullptr, false, true, nullptr))
|
||||||
, m_iSampleRate(0)
|
, wo_buffers_{}
|
||||||
, m_bShutdown(false)
|
, wo_samplerate_(0)
|
||||||
, b_InitSuccess(false)
|
, wo_shutdown_(false)
|
||||||
, NUM_CHUNKS(1)
|
, wo_last_cursor_position_(0)
|
||||||
, BUFFERSIZE_FRAMES(0)
|
, wo_init_success_(false)
|
||||||
, CHUNKSIZE(0)
|
, wo_frames_per_block_(0)
|
||||||
, m_aBuffers{}
|
, wo_num_blocks_(1)
|
||||||
, MixingThread()
|
, wo_blocksize_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RString RageSoundDriver_WaveOut::Init()
|
RString RageSoundDriver_WaveOut::Init()
|
||||||
{
|
{
|
||||||
b_InitSuccess = false;
|
wo_init_success_ = false;
|
||||||
m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate;
|
wo_samplerate_ = PREFSMAN->m_iSoundPreferredSampleRate;
|
||||||
if( m_iSampleRate == 0 )
|
if( wo_samplerate_ == 0 )
|
||||||
{
|
{
|
||||||
m_iSampleRate = kFallbackSampleRate;
|
wo_samplerate_ = kFallbackSampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
NUM_CHUNKS = CalculateNumBlocks( m_iSampleRate );
|
wo_num_blocks_ = CalculateNumBlocks( wo_samplerate_ );
|
||||||
BUFFERSIZE_FRAMES = CHUNKSIZE_FRAMES * NUM_CHUNKS;
|
|
||||||
CHUNKSIZE = CHUNKSIZE_FRAMES * BYTES_PER_FRAME;
|
wo_frames_per_block_ = kBlockSizeFrames * wo_num_blocks_;
|
||||||
|
wo_blocksize_ = kBlockSizeFrames * kBytesPerFrame;
|
||||||
|
|
||||||
WAVEFORMATEX fmt;
|
WAVEFORMATEX fmt;
|
||||||
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
fmt.nChannels = CHANNELS;
|
fmt.nChannels = kChannels;
|
||||||
fmt.cbSize = 0;
|
fmt.cbSize = 0;
|
||||||
fmt.nSamplesPerSec = m_iSampleRate;
|
fmt.nSamplesPerSec = wo_samplerate_;
|
||||||
fmt.wBitsPerSample = 16;
|
|
||||||
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
|
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
|
||||||
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
||||||
|
|
||||||
@@ -178,7 +172,7 @@ RString RageSoundDriver_WaveOut::Init()
|
|||||||
|
|
||||||
MMRESULT ret = MMSYSERR_ERROR;
|
MMRESULT ret = MMSYSERR_ERROR;
|
||||||
for (UINT id : deviceIds) {
|
for (UINT id : deviceIds) {
|
||||||
ret = waveOutOpen( &m_hWaveOut, id, &fmt, (DWORD_PTR) m_hSoundEvent, NULL, CALLBACK_EVENT );
|
ret = waveOutOpen( &waveout_handle_, id, &fmt, (DWORD_PTR) soundevent_handle_, NULL, CALLBACK_EVENT );
|
||||||
if (ret == MMSYSERR_NOERROR) {
|
if (ret == MMSYSERR_NOERROR) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -188,28 +182,28 @@ RString RageSoundDriver_WaveOut::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZERO( m_aBuffers );
|
ZERO( wo_buffers_ );
|
||||||
for(int b = 0; b < NUM_CHUNKS; ++b)
|
for(int b = 0; b < wo_num_blocks_; ++b)
|
||||||
{
|
{
|
||||||
m_aBuffers[b].dwBufferLength = CHUNKSIZE;
|
wo_buffers_[b].dwBufferLength = wo_blocksize_;
|
||||||
m_aBuffers[b].lpData = new char[CHUNKSIZE];
|
wo_buffers_[b].lpData = new char[wo_blocksize_];
|
||||||
ret = waveOutPrepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
ret = waveOutPrepareHeader( waveout_handle_, &wo_buffers_[b], sizeof(wo_buffers_[b]) );
|
||||||
if( ret != MMSYSERR_NOERROR )
|
if( ret != MMSYSERR_NOERROR )
|
||||||
return wo_ssprintf( ret, "waveOutPrepareHeader failed" );
|
return wo_ssprintf( ret, "waveOutPrepareHeader failed" );
|
||||||
m_aBuffers[b].dwFlags |= WHDR_DONE;
|
wo_buffers_[b].dwFlags |= WHDR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG->Info( "WaveOut software mixing at %i hz", m_iSampleRate );
|
LOG->Info( "WaveOut software mixing at %i hz", wo_samplerate_ );
|
||||||
|
|
||||||
/* We have a very large writeahead; make sure we have a large enough decode
|
/* We have a very large writeahead; make sure we have a large enough decode
|
||||||
* buffer to recover cleanly from underruns. */
|
* buffer to recover cleanly from underruns. */
|
||||||
SetDecodeBufferSize( BUFFERSIZE_FRAMES * 3/2 );
|
SetDecodeBufferSize( wo_frames_per_block_ * 3/2 );
|
||||||
StartDecodeThread();
|
StartDecodeThread();
|
||||||
|
|
||||||
MixingThread.SetName( "Mixer thread" );
|
MixingThread.SetName( "Mixer thread" );
|
||||||
MixingThread.Create( MixerThread_start, this );
|
MixingThread.Create( MixerThread_start, this );
|
||||||
|
|
||||||
b_InitSuccess = true;
|
wo_init_success_ = true;
|
||||||
return RString();
|
return RString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,32 +212,32 @@ RageSoundDriver_WaveOut::~RageSoundDriver_WaveOut()
|
|||||||
/* Signal the mixing thread to quit. */
|
/* Signal the mixing thread to quit. */
|
||||||
if( MixingThread.IsCreated() )
|
if( MixingThread.IsCreated() )
|
||||||
{
|
{
|
||||||
m_bShutdown = true;
|
wo_shutdown_ = true;
|
||||||
SetEvent( m_hSoundEvent );
|
SetEvent( soundevent_handle_ );
|
||||||
LOG->Trace( "Shutting down mixer thread ..." );
|
LOG->Trace( "Shutting down mixer thread ..." );
|
||||||
MixingThread.Wait();
|
MixingThread.Wait();
|
||||||
LOG->Trace( "Mixer thread shut down." );
|
LOG->Trace( "Mixer thread shut down." );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_hWaveOut != nullptr )
|
if( waveout_handle_ != nullptr )
|
||||||
{
|
{
|
||||||
for( int b = 0; b < NUM_CHUNKS && m_aBuffers[b].lpData != nullptr; ++b )
|
for( int b = 0; b < wo_num_blocks_ && wo_buffers_[b].lpData != nullptr; ++b )
|
||||||
{
|
{
|
||||||
waveOutUnprepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
waveOutUnprepareHeader( waveout_handle_, &wo_buffers_[b], sizeof(wo_buffers_[b]) );
|
||||||
delete [] m_aBuffers[b].lpData;
|
delete [] wo_buffers_[b].lpData;
|
||||||
}
|
}
|
||||||
|
|
||||||
waveOutClose( m_hWaveOut );
|
waveOutClose( waveout_handle_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle( m_hSoundEvent );
|
CloseHandle( soundevent_handle_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
float RageSoundDriver_WaveOut::GetPlayLatency() const
|
float RageSoundDriver_WaveOut::GetPlayLatency() const
|
||||||
{
|
{
|
||||||
/* If we have a 1000-byte buffer, and we fill 100 bytes at a time, we
|
/* If we have a 1000-byte buffer, and we fill 100 bytes at a time, we
|
||||||
* almost always have between 900 and 1000 bytes filled; on average, 950. */
|
* almost always have between 900 and 1000 bytes filled; on average, 950. */
|
||||||
return (BUFFERSIZE_FRAMES - CHUNKSIZE_FRAMES/2) * (1.0f / m_iSampleRate);
|
return (wo_frames_per_block_ - kBlockSizeFrames/2) * (1.0f / wo_samplerate_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -12,12 +12,19 @@
|
|||||||
class RageSoundDriver_WaveOut: public RageSoundDriver
|
class RageSoundDriver_WaveOut: public RageSoundDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// The size of wo_buffers_ is the -maximum- number of blocks we can have.
|
||||||
|
// We have to pre-allocate this size here. With the default target latency
|
||||||
|
// of 118 ms, 13 buffers is sufficient for both 44100 and 48000 Hz sample
|
||||||
|
// rates, but at least 20 buffers are needed if higher sample rates (such
|
||||||
|
// as 96000 Hz) are used, or the game will crash during initialization.
|
||||||
|
static const int kMaximumNumBlocks = 32;
|
||||||
|
|
||||||
RageSoundDriver_WaveOut();
|
RageSoundDriver_WaveOut();
|
||||||
~RageSoundDriver_WaveOut();
|
~RageSoundDriver_WaveOut();
|
||||||
RString Init();
|
RString Init();
|
||||||
int64_t GetPosition() const;
|
int64_t GetPosition() const;
|
||||||
float GetPlayLatency() const;
|
float GetPlayLatency() const;
|
||||||
int GetSampleRate() const { return m_iSampleRate; }
|
int GetSampleRate() const { return wo_samplerate_; }
|
||||||
private:
|
private:
|
||||||
static int MixerThread_start( void *p );
|
static int MixerThread_start( void *p );
|
||||||
void MixerThread();
|
void MixerThread();
|
||||||
@@ -25,16 +32,16 @@ private:
|
|||||||
bool GetData();
|
bool GetData();
|
||||||
void SetupDecodingThread();
|
void SetupDecodingThread();
|
||||||
|
|
||||||
HWAVEOUT m_hWaveOut;
|
HWAVEOUT waveout_handle_;
|
||||||
HANDLE m_hSoundEvent;
|
HANDLE soundevent_handle_;
|
||||||
WAVEHDR m_aBuffers[32]; // Maximum of 32 output blocks (frame blocks) allowed.
|
WAVEHDR wo_buffers_[kMaximumNumBlocks];
|
||||||
int m_iSampleRate;
|
int wo_samplerate_;
|
||||||
bool m_bShutdown;
|
bool wo_shutdown_;
|
||||||
int m_iLastCursorPos;
|
int wo_last_cursor_position_;
|
||||||
bool b_InitSuccess;
|
bool wo_init_success_;
|
||||||
int NUM_CHUNKS; // TODO rename wo_num_blocks
|
int wo_frames_per_block_;
|
||||||
int BUFFERSIZE_FRAMES; // TODO rename wo_num_frames_per_block
|
int wo_num_blocks_;
|
||||||
int CHUNKSIZE; // TODO rename wo_block_size
|
int wo_blocksize_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user