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
|
||||
// of blocks and buffer size in frames based on the sample rate.
|
||||
constexpr int kTargetLatency = 118;
|
||||
|
||||
// CHANNELS should be renamed CHANNELS
|
||||
constexpr int CHANNELS = 2;
|
||||
|
||||
// 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
|
||||
constexpr int kChannels = 2;
|
||||
constexpr int kBlockSizeFrames = 512;
|
||||
constexpr int kBytesPerFrame = kChannels * 2; // 16 bit
|
||||
|
||||
inline int CalculateNumBlocks( int sampleRate )
|
||||
{
|
||||
return (sampleRate * kTargetLatency +
|
||||
(1000 * CHUNKSIZE_FRAMES - 1)) /
|
||||
(1000 * CHUNKSIZE_FRAMES);
|
||||
(1000 * kBlockSizeFrames - 1)) /
|
||||
(1000 * kBlockSizeFrames);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -69,42 +63,42 @@ void RageSoundDriver_WaveOut::MixerThread()
|
||||
if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) )
|
||||
LOG->Warn( werr_ssprintf(GetLastError(), "Failed to set sound thread priority") );
|
||||
|
||||
while( !m_bShutdown )
|
||||
while( !wo_shutdown_ )
|
||||
{
|
||||
while( GetData() )
|
||||
;
|
||||
|
||||
WaitForSingleObject( m_hSoundEvent, 10 );
|
||||
WaitForSingleObject( soundevent_handle_, 10 );
|
||||
}
|
||||
|
||||
waveOutReset( m_hWaveOut );
|
||||
waveOutReset( waveout_handle_ );
|
||||
}
|
||||
|
||||
bool RageSoundDriver_WaveOut::GetData()
|
||||
{
|
||||
/* Look for a free buffer. */
|
||||
int b;
|
||||
for( b = 0; b < NUM_CHUNKS; ++b )
|
||||
if( m_aBuffers[b].dwFlags & WHDR_DONE )
|
||||
for( b = 0; b < wo_num_blocks_; ++b )
|
||||
if( wo_buffers_[b].dwFlags & WHDR_DONE )
|
||||
break;
|
||||
if( b == NUM_CHUNKS )
|
||||
if( b == wo_num_blocks_ )
|
||||
return false;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
Init();
|
||||
if (b_InitSuccess == false)
|
||||
if (wo_init_success_ == false)
|
||||
{
|
||||
FAIL_M(wo_ssprintf(ret, "waveOutWrite failed"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment m_iLastCursorPos. */
|
||||
m_iLastCursorPos += CHUNKSIZE_FRAMES;
|
||||
/* Increment wo_last_cursor_position_. */
|
||||
wo_last_cursor_position_ += kBlockSizeFrames;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -119,7 +113,7 @@ int64_t RageSoundDriver_WaveOut::GetPosition() const
|
||||
{
|
||||
MMTIME tm;
|
||||
tm.wType = TIME_SAMPLES;
|
||||
MMRESULT ret = waveOutGetPosition( m_hWaveOut, &tm, sizeof(tm) );
|
||||
MMRESULT ret = waveOutGetPosition( waveout_handle_, &tm, sizeof(tm) );
|
||||
if( ret != MMSYSERR_NOERROR )
|
||||
FAIL_M( wo_ssprintf(ret, "waveOutGetPosition failed") );
|
||||
|
||||
@@ -127,39 +121,39 @@ int64_t RageSoundDriver_WaveOut::GetPosition() const
|
||||
}
|
||||
|
||||
RageSoundDriver_WaveOut::RageSoundDriver_WaveOut()
|
||||
: m_hWaveOut(nullptr)
|
||||
, m_hSoundEvent(CreateEvent(nullptr, false, true, nullptr))
|
||||
, m_iLastCursorPos(0)
|
||||
, m_iSampleRate(0)
|
||||
, m_bShutdown(false)
|
||||
, b_InitSuccess(false)
|
||||
, NUM_CHUNKS(1)
|
||||
, BUFFERSIZE_FRAMES(0)
|
||||
, CHUNKSIZE(0)
|
||||
, m_aBuffers{}
|
||||
, MixingThread()
|
||||
: MixingThread()
|
||||
, waveout_handle_(nullptr)
|
||||
, soundevent_handle_(CreateEvent(nullptr, false, true, nullptr))
|
||||
, wo_buffers_{}
|
||||
, wo_samplerate_(0)
|
||||
, wo_shutdown_(false)
|
||||
, wo_last_cursor_position_(0)
|
||||
, wo_init_success_(false)
|
||||
, wo_frames_per_block_(0)
|
||||
, wo_num_blocks_(1)
|
||||
, wo_blocksize_(0)
|
||||
{
|
||||
}
|
||||
|
||||
RString RageSoundDriver_WaveOut::Init()
|
||||
{
|
||||
b_InitSuccess = false;
|
||||
m_iSampleRate = PREFSMAN->m_iSoundPreferredSampleRate;
|
||||
if( m_iSampleRate == 0 )
|
||||
wo_init_success_ = false;
|
||||
wo_samplerate_ = PREFSMAN->m_iSoundPreferredSampleRate;
|
||||
if( wo_samplerate_ == 0 )
|
||||
{
|
||||
m_iSampleRate = kFallbackSampleRate;
|
||||
wo_samplerate_ = kFallbackSampleRate;
|
||||
}
|
||||
|
||||
NUM_CHUNKS = CalculateNumBlocks( m_iSampleRate );
|
||||
BUFFERSIZE_FRAMES = CHUNKSIZE_FRAMES * NUM_CHUNKS;
|
||||
CHUNKSIZE = CHUNKSIZE_FRAMES * BYTES_PER_FRAME;
|
||||
wo_num_blocks_ = CalculateNumBlocks( wo_samplerate_ );
|
||||
|
||||
wo_frames_per_block_ = kBlockSizeFrames * wo_num_blocks_;
|
||||
wo_blocksize_ = kBlockSizeFrames * kBytesPerFrame;
|
||||
|
||||
WAVEFORMATEX fmt;
|
||||
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
fmt.nChannels = CHANNELS;
|
||||
fmt.nChannels = kChannels;
|
||||
fmt.cbSize = 0;
|
||||
fmt.nSamplesPerSec = m_iSampleRate;
|
||||
fmt.wBitsPerSample = 16;
|
||||
fmt.nSamplesPerSec = wo_samplerate_;
|
||||
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
|
||||
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
||||
|
||||
@@ -178,7 +172,7 @@ RString RageSoundDriver_WaveOut::Init()
|
||||
|
||||
MMRESULT ret = MMSYSERR_ERROR;
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
@@ -188,28 +182,28 @@ RString RageSoundDriver_WaveOut::Init()
|
||||
}
|
||||
|
||||
|
||||
ZERO( m_aBuffers );
|
||||
for(int b = 0; b < NUM_CHUNKS; ++b)
|
||||
ZERO( wo_buffers_ );
|
||||
for(int b = 0; b < wo_num_blocks_; ++b)
|
||||
{
|
||||
m_aBuffers[b].dwBufferLength = CHUNKSIZE;
|
||||
m_aBuffers[b].lpData = new char[CHUNKSIZE];
|
||||
ret = waveOutPrepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
||||
wo_buffers_[b].dwBufferLength = wo_blocksize_;
|
||||
wo_buffers_[b].lpData = new char[wo_blocksize_];
|
||||
ret = waveOutPrepareHeader( waveout_handle_, &wo_buffers_[b], sizeof(wo_buffers_[b]) );
|
||||
if( ret != MMSYSERR_NOERROR )
|
||||
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
|
||||
* buffer to recover cleanly from underruns. */
|
||||
SetDecodeBufferSize( BUFFERSIZE_FRAMES * 3/2 );
|
||||
SetDecodeBufferSize( wo_frames_per_block_ * 3/2 );
|
||||
StartDecodeThread();
|
||||
|
||||
MixingThread.SetName( "Mixer thread" );
|
||||
MixingThread.Create( MixerThread_start, this );
|
||||
|
||||
b_InitSuccess = true;
|
||||
wo_init_success_ = true;
|
||||
return RString();
|
||||
}
|
||||
|
||||
@@ -218,32 +212,32 @@ RageSoundDriver_WaveOut::~RageSoundDriver_WaveOut()
|
||||
/* Signal the mixing thread to quit. */
|
||||
if( MixingThread.IsCreated() )
|
||||
{
|
||||
m_bShutdown = true;
|
||||
SetEvent( m_hSoundEvent );
|
||||
wo_shutdown_ = true;
|
||||
SetEvent( soundevent_handle_ );
|
||||
LOG->Trace( "Shutting down mixer thread ..." );
|
||||
MixingThread.Wait();
|
||||
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]) );
|
||||
delete [] m_aBuffers[b].lpData;
|
||||
waveOutUnprepareHeader( waveout_handle_, &wo_buffers_[b], sizeof(wo_buffers_[b]) );
|
||||
delete [] wo_buffers_[b].lpData;
|
||||
}
|
||||
|
||||
waveOutClose( m_hWaveOut );
|
||||
waveOutClose( waveout_handle_ );
|
||||
}
|
||||
|
||||
CloseHandle( m_hSoundEvent );
|
||||
CloseHandle( soundevent_handle_ );
|
||||
}
|
||||
|
||||
float RageSoundDriver_WaveOut::GetPlayLatency() const
|
||||
{
|
||||
/* 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. */
|
||||
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
|
||||
{
|
||||
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();
|
||||
RString Init();
|
||||
int64_t GetPosition() const;
|
||||
float GetPlayLatency() const;
|
||||
int GetSampleRate() const { return m_iSampleRate; }
|
||||
int GetSampleRate() const { return wo_samplerate_; }
|
||||
private:
|
||||
static int MixerThread_start( void *p );
|
||||
void MixerThread();
|
||||
@@ -25,16 +32,16 @@ private:
|
||||
bool GetData();
|
||||
void SetupDecodingThread();
|
||||
|
||||
HWAVEOUT m_hWaveOut;
|
||||
HANDLE m_hSoundEvent;
|
||||
WAVEHDR m_aBuffers[32]; // Maximum of 32 output blocks (frame blocks) allowed.
|
||||
int m_iSampleRate;
|
||||
bool m_bShutdown;
|
||||
int m_iLastCursorPos;
|
||||
bool b_InitSuccess;
|
||||
int NUM_CHUNKS; // TODO rename wo_num_blocks
|
||||
int BUFFERSIZE_FRAMES; // TODO rename wo_num_frames_per_block
|
||||
int CHUNKSIZE; // TODO rename wo_block_size
|
||||
HWAVEOUT waveout_handle_;
|
||||
HANDLE soundevent_handle_;
|
||||
WAVEHDR wo_buffers_[kMaximumNumBlocks];
|
||||
int wo_samplerate_;
|
||||
bool wo_shutdown_;
|
||||
int wo_last_cursor_position_;
|
||||
bool wo_init_success_;
|
||||
int wo_frames_per_block_;
|
||||
int wo_num_blocks_;
|
||||
int wo_blocksize_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user