WaveOut 16x512 buffer instead of 8x1024
Both come out to the same amount of target latency (as does 32x256, etc) however RageSoundDriver.h defines samples_per_block as 512, so this aims to have chunksize_frames equal 512. It also defines a constant to define the quantity of buffers so it's not hardcoded in various places and puts the variables in an anonymous namespace.
This commit is contained in:
@@ -19,14 +19,15 @@
|
|||||||
|
|
||||||
REGISTER_SOUND_DRIVER_CLASS( WaveOut );
|
REGISTER_SOUND_DRIVER_CLASS( WaveOut );
|
||||||
|
|
||||||
const int channels = 2;
|
namespace {
|
||||||
const int bytes_per_frame = channels*2; /* 16-bit */
|
const int CHANNELS = 2;
|
||||||
const int buffersize_frames = 1024*8; /* in frames */
|
const int BYTES_PER_FRAME = CHANNELS * 2; // 16 bit
|
||||||
const int buffersize = buffersize_frames * bytes_per_frame; /* in bytes */
|
const int BUFFERSIZE_FRAMES = 512 * RageSoundDriver_WaveOut::NUM_BUFFERS; // in frames
|
||||||
|
const int BUFFERSIZE = BUFFERSIZE_FRAMES * BYTES_PER_FRAME; // in bytes
|
||||||
const int num_chunks = 8;
|
const int NUM_CHUNKS = RageSoundDriver_WaveOut::NUM_BUFFERS;
|
||||||
const int chunksize_frames = buffersize_frames / num_chunks;
|
const int CHUNKSIZE_FRAMES = BUFFERSIZE_FRAMES / NUM_CHUNKS; // in frames
|
||||||
const int chunksize = buffersize / num_chunks; /* in bytes */
|
const int CHUNKSIZE = CHUNKSIZE_FRAMES * BYTES_PER_FRAME; // in bytes
|
||||||
|
} // namespace
|
||||||
|
|
||||||
static RString wo_ssprintf( MMRESULT err, const char *szFmt, ...)
|
static RString wo_ssprintf( MMRESULT err, const char *szFmt, ...)
|
||||||
{
|
{
|
||||||
@@ -67,14 +68,14 @@ 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 < NUM_CHUNKS; ++b )
|
||||||
if( m_aBuffers[b].dwFlags & WHDR_DONE )
|
if( m_aBuffers[b].dwFlags & WHDR_DONE )
|
||||||
break;
|
break;
|
||||||
if( b == num_chunks )
|
if( b == NUM_CHUNKS )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Call the callback. */
|
/* Call the callback. */
|
||||||
this->Mix( (std::int16_t *) m_aBuffers[b].lpData, chunksize_frames, m_iLastCursorPos, GetPosition() );
|
this->Mix( (std::int16_t *) m_aBuffers[b].lpData, CHUNKSIZE_FRAMES, m_iLastCursorPos, GetPosition() );
|
||||||
|
|
||||||
MMRESULT ret = waveOutWrite( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
MMRESULT ret = waveOutWrite( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
||||||
if( ret != MMSYSERR_NOERROR )
|
if( ret != MMSYSERR_NOERROR )
|
||||||
@@ -87,7 +88,7 @@ bool RageSoundDriver_WaveOut::GetData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Increment m_iLastCursorPos. */
|
/* Increment m_iLastCursorPos. */
|
||||||
m_iLastCursorPos += chunksize_frames;
|
m_iLastCursorPos += CHUNKSIZE_FRAMES;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -128,7 +129,7 @@ RString RageSoundDriver_WaveOut::Init()
|
|||||||
|
|
||||||
WAVEFORMATEX fmt;
|
WAVEFORMATEX fmt;
|
||||||
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
fmt.nChannels = channels;
|
fmt.nChannels = CHANNELS;
|
||||||
fmt.cbSize = 0;
|
fmt.cbSize = 0;
|
||||||
fmt.nSamplesPerSec = m_iSampleRate;
|
fmt.nSamplesPerSec = m_iSampleRate;
|
||||||
fmt.wBitsPerSample = 16;
|
fmt.wBitsPerSample = 16;
|
||||||
@@ -161,10 +162,10 @@ RString RageSoundDriver_WaveOut::Init()
|
|||||||
|
|
||||||
|
|
||||||
ZERO( m_aBuffers );
|
ZERO( m_aBuffers );
|
||||||
for(int b = 0; b < num_chunks; ++b)
|
for(int b = 0; b < NUM_CHUNKS; ++b)
|
||||||
{
|
{
|
||||||
m_aBuffers[b].dwBufferLength = chunksize;
|
m_aBuffers[b].dwBufferLength = CHUNKSIZE;
|
||||||
m_aBuffers[b].lpData = new char[chunksize];
|
m_aBuffers[b].lpData = new char[CHUNKSIZE];
|
||||||
ret = waveOutPrepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
ret = waveOutPrepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
||||||
if( ret != MMSYSERR_NOERROR )
|
if( ret != MMSYSERR_NOERROR )
|
||||||
return wo_ssprintf( ret, "waveOutPrepareHeader failed" );
|
return wo_ssprintf( ret, "waveOutPrepareHeader failed" );
|
||||||
@@ -175,7 +176,7 @@ RString RageSoundDriver_WaveOut::Init()
|
|||||||
|
|
||||||
/* 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( BUFFERSIZE_FRAMES * 3/2 );
|
||||||
StartDecodeThread();
|
StartDecodeThread();
|
||||||
|
|
||||||
MixingThread.SetName( "Mixer thread" );
|
MixingThread.SetName( "Mixer thread" );
|
||||||
@@ -199,7 +200,7 @@ RageSoundDriver_WaveOut::~RageSoundDriver_WaveOut()
|
|||||||
|
|
||||||
if( m_hWaveOut != nullptr )
|
if( m_hWaveOut != nullptr )
|
||||||
{
|
{
|
||||||
for( int b = 0; b < num_chunks && m_aBuffers[b].lpData != nullptr; ++b )
|
for( int b = 0; b < NUM_CHUNKS && m_aBuffers[b].lpData != nullptr; ++b )
|
||||||
{
|
{
|
||||||
waveOutUnprepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
waveOutUnprepareHeader( m_hWaveOut, &m_aBuffers[b], sizeof(m_aBuffers[b]) );
|
||||||
delete [] m_aBuffers[b].lpData;
|
delete [] m_aBuffers[b].lpData;
|
||||||
@@ -215,7 +216,7 @@ 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 (BUFFERSIZE_FRAMES - CHUNKSIZE_FRAMES/2) * (1.0f / m_iSampleRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
std::int64_t GetPosition() const;
|
std::int64_t GetPosition() const;
|
||||||
float GetPlayLatency() const;
|
float GetPlayLatency() const;
|
||||||
int GetSampleRate() const { return m_iSampleRate; }
|
int GetSampleRate() const { return m_iSampleRate; }
|
||||||
|
static const int NUM_BUFFERS = 32;
|
||||||
private:
|
private:
|
||||||
static int MixerThread_start( void *p );
|
static int MixerThread_start( void *p );
|
||||||
void MixerThread();
|
void MixerThread();
|
||||||
@@ -28,7 +28,7 @@ private:
|
|||||||
|
|
||||||
HWAVEOUT m_hWaveOut;
|
HWAVEOUT m_hWaveOut;
|
||||||
HANDLE m_hSoundEvent;
|
HANDLE m_hSoundEvent;
|
||||||
WAVEHDR m_aBuffers[8];
|
WAVEHDR m_aBuffers[NUM_BUFFERS];
|
||||||
int m_iSampleRate;
|
int m_iSampleRate;
|
||||||
bool m_bShutdown;
|
bool m_bShutdown;
|
||||||
int m_iLastCursorPos;
|
int m_iLastCursorPos;
|
||||||
|
|||||||
Reference in New Issue
Block a user