style cleanup
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "../../global.h"
|
||||
#include "global.h"
|
||||
#include "DSoundHelpers.h"
|
||||
#include "../../RageUtil.h"
|
||||
#include "../../RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "archutils/Win32/GetFileInformation.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
@@ -25,9 +25,9 @@ BOOL CALLBACK DSound::EnumCallback( LPGUID lpGuid, LPCSTR lpcstrDescription, LPC
|
||||
CString sPath = FindSystemFile( lpcstrModule );
|
||||
if( sPath != "" )
|
||||
{
|
||||
CString ver;
|
||||
if( GetFileVersion( sPath, ver ) )
|
||||
sLine += ssprintf(" %s", ver.c_str());
|
||||
CString sVersion;
|
||||
if( GetFileVersion(sPath, sVersion) )
|
||||
sLine += ssprintf( " %s", sVersion.c_str() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -47,8 +47,8 @@ void DSound::SetPrimaryBufferMode()
|
||||
format.dwBufferBytes = 0;
|
||||
format.lpwfxFormat = NULL;
|
||||
|
||||
IDirectSoundBuffer *buf;
|
||||
HRESULT hr = this->GetDS()->CreateSoundBuffer(&format, &buf, NULL);
|
||||
IDirectSoundBuffer *pBuffer;
|
||||
HRESULT hr = this->GetDS()->CreateSoundBuffer( &format, &pBuffer, NULL );
|
||||
/* hr */
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
@@ -56,10 +56,10 @@ void DSound::SetPrimaryBufferMode()
|
||||
return;
|
||||
}
|
||||
|
||||
WAVEFORMATEX waveformat;
|
||||
WAVEFORMATEX waveformat;
|
||||
memset( &waveformat, 0, sizeof(waveformat) );
|
||||
waveformat.cbSize = 0;
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveformat.cbSize = 0;
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveformat.wBitsPerSample = 16;
|
||||
waveformat.nChannels = 2;
|
||||
waveformat.nSamplesPerSec = 44100;
|
||||
@@ -67,12 +67,12 @@ void DSound::SetPrimaryBufferMode()
|
||||
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
|
||||
|
||||
// Set the primary buffer's format
|
||||
hr = IDirectSoundBuffer_SetFormat( buf, &waveformat );
|
||||
hr = IDirectSoundBuffer_SetFormat( pBuffer, &waveformat );
|
||||
if( FAILED(hr) )
|
||||
LOG->Warn( hr_ssprintf(hr, "SetFormat on primary buffer") );
|
||||
|
||||
DWORD got;
|
||||
hr = buf->GetFormat( &waveformat, sizeof(waveformat), &got );
|
||||
hr = pBuffer->GetFormat( &waveformat, sizeof(waveformat), &got );
|
||||
if( FAILED(hr) )
|
||||
LOG->Warn( hr_ssprintf(hr, "GetFormat on primary buffer") );
|
||||
else if( waveformat.nSamplesPerSec != 44100 )
|
||||
@@ -92,25 +92,23 @@ void DSound::SetPrimaryBufferMode()
|
||||
*
|
||||
* However, I just added the above code and I don't want to change more until it's tested.
|
||||
*/
|
||||
// buf->Play(0, 0, DSBPLAY_LOOPING);
|
||||
// pBuffer->Play( 0, 0, DSBPLAY_LOOPING );
|
||||
|
||||
buf->Release();
|
||||
pBuffer->Release();
|
||||
#endif
|
||||
}
|
||||
|
||||
DSound::DSound()
|
||||
{
|
||||
// Initialize COM
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = CoInitialize( NULL ) ) )
|
||||
RageException::Throw(hr_ssprintf(hr, "CoInitialize"));
|
||||
if( FAILED( hr = CoInitialize(NULL) ) )
|
||||
RageException::Throw( hr_ssprintf(hr, "CoInitialize") );
|
||||
}
|
||||
|
||||
CString DSound::Init()
|
||||
{
|
||||
// Create IDirectSound using the primary sound device
|
||||
HRESULT hr;
|
||||
if( FAILED( hr = DirectSoundCreate( NULL, &ds, NULL ) ) )
|
||||
if( FAILED( hr = DirectSoundCreate(NULL, &m_pDS, NULL) ) )
|
||||
return hr_ssprintf( hr, "DirectSoundCreate" );
|
||||
|
||||
#ifndef _XBOX
|
||||
@@ -118,14 +116,14 @@ CString DSound::Init()
|
||||
if( !bShownInfo )
|
||||
{
|
||||
bShownInfo = true;
|
||||
DirectSoundEnumerate(EnumCallback, 0);
|
||||
DirectSoundEnumerate( EnumCallback, 0 );
|
||||
|
||||
DSCAPS Caps;
|
||||
Caps.dwSize = sizeof(Caps);
|
||||
HRESULT hr;
|
||||
if( FAILED(hr = ds->GetCaps(&Caps)) )
|
||||
if( FAILED(hr = m_pDS->GetCaps(&Caps)) )
|
||||
{
|
||||
LOG->Warn( hr_ssprintf(hr, "ds->GetCaps failed") );
|
||||
LOG->Warn( hr_ssprintf(hr, "m_pDS->GetCaps failed") );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +133,7 @@ CString DSound::Init()
|
||||
}
|
||||
|
||||
/* Try to set primary mixing privileges */
|
||||
hr = ds->SetCooperativeLevel( GetDesktopWindow(), DSSCL_PRIORITY );
|
||||
hr = m_pDS->SetCooperativeLevel( GetDesktopWindow(), DSSCL_PRIORITY );
|
||||
#endif
|
||||
|
||||
SetPrimaryBufferMode();
|
||||
@@ -145,8 +143,8 @@ CString DSound::Init()
|
||||
|
||||
DSound::~DSound()
|
||||
{
|
||||
ds->Release();
|
||||
CoUninitialize();
|
||||
m_pDS->Release();
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool DSound::IsEmulated() const
|
||||
@@ -157,9 +155,9 @@ bool DSound::IsEmulated() const
|
||||
DSCAPS Caps;
|
||||
Caps.dwSize = sizeof(Caps);
|
||||
HRESULT hr;
|
||||
if( FAILED(hr = ds->GetCaps(&Caps)) )
|
||||
if( FAILED(hr = m_pDS->GetCaps(&Caps)) )
|
||||
{
|
||||
LOG->Warn( hr_ssprintf(hr, "ds->GetCaps failed") );
|
||||
LOG->Warn( hr_ssprintf(hr, "m_pDS->GetCaps failed") );
|
||||
/* This is strange, so let's be conservative. */
|
||||
return true;
|
||||
}
|
||||
@@ -172,30 +170,29 @@ bool DSound::IsEmulated() const
|
||||
|
||||
DSoundBuf::DSoundBuf()
|
||||
{
|
||||
buf = NULL;
|
||||
temp_buffer = NULL;
|
||||
m_pBuffer = NULL;
|
||||
m_pTempBuffer = NULL;
|
||||
}
|
||||
|
||||
CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
int channels_, int samplerate_, int samplebits_, int writeahead_ )
|
||||
int iChannels, int iSampleRate, int iSampleBits, int iWriteAhead )
|
||||
{
|
||||
|
||||
channels = channels_;
|
||||
samplerate = samplerate_;
|
||||
samplebits = samplebits_;
|
||||
writeahead = writeahead_ * bytes_per_frame();
|
||||
volume = -1; /* unset */
|
||||
buffer_locked = false;
|
||||
write_cursor_pos = write_cursor = buffer_bytes_filled = 0;
|
||||
extra_writeahead = 0;
|
||||
LastPosition = 0;
|
||||
playing = false;
|
||||
ZERO( last_cursors );
|
||||
m_iChannels = iChannels;
|
||||
m_iSampleRate = iSampleRate;
|
||||
m_iSampleBits = iSampleBits;
|
||||
m_iWriteAhead = iWriteAhead * bytes_per_frame();
|
||||
m_iVolume = -1; /* unset */
|
||||
m_bBufferLocked = false;
|
||||
m_iWriteCursorPos = m_iWriteCursor = m_iBufferBytesFilled = 0;
|
||||
m_iExtraWriteahead = 0;
|
||||
m_iLastPosition = 0;
|
||||
m_bPlaying = false;
|
||||
ZERO( m_iLastCursors );
|
||||
|
||||
/* The size of the actual DSound buffer. This can be large; we generally
|
||||
* won't fill it completely. */
|
||||
buffersize = 1024*64;
|
||||
buffersize = max( buffersize, writeahead );
|
||||
m_iBufferSize = 1024*64;
|
||||
m_iBufferSize = max( m_iBufferSize, m_iWriteAhead );
|
||||
|
||||
WAVEFORMATEX waveformat;
|
||||
memset( &waveformat, 0, sizeof(waveformat) );
|
||||
@@ -203,18 +200,18 @@ CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
|
||||
bool NeedCtrlFrequency = false;
|
||||
if( samplerate == DYNAMIC_SAMPLERATE )
|
||||
if( m_iSampleRate == DYNAMIC_SAMPLERATE )
|
||||
{
|
||||
samplerate = 44100;
|
||||
m_iSampleRate = 44100;
|
||||
NeedCtrlFrequency = true;
|
||||
}
|
||||
|
||||
int bytes = samplebits/8;
|
||||
waveformat.wBitsPerSample = WORD(samplebits);
|
||||
waveformat.nChannels = WORD(channels);
|
||||
waveformat.nSamplesPerSec = DWORD(samplerate);
|
||||
waveformat.nBlockAlign = WORD(bytes*channels);
|
||||
waveformat.nAvgBytesPerSec = samplerate * bytes*channels;
|
||||
int bytes = m_iSampleBits / 8;
|
||||
waveformat.wBitsPerSample = WORD(m_iSampleBits);
|
||||
waveformat.nChannels = WORD(m_iChannels);
|
||||
waveformat.nSamplesPerSec = DWORD(m_iSampleRate);
|
||||
waveformat.nBlockAlign = WORD(bytes*m_iChannels);
|
||||
waveformat.nAvgBytesPerSec = m_iSampleRate * bytes*m_iChannels;
|
||||
|
||||
/* Try to create the secondary buffer */
|
||||
DSBUFFERDESC format;
|
||||
@@ -238,20 +235,20 @@ CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
if( NeedCtrlFrequency )
|
||||
format.dwFlags |= DSBCAPS_CTRLFREQUENCY;
|
||||
|
||||
format.dwBufferBytes = buffersize;
|
||||
format.dwBufferBytes = m_iBufferSize;
|
||||
#ifndef _XBOX
|
||||
format.dwReserved = 0;
|
||||
#else
|
||||
DSMIXBINVOLUMEPAIR dsmbvp[8] =
|
||||
{
|
||||
{ DSMIXBIN_FRONT_LEFT, DSBVOLUME_MAX}, // left channel
|
||||
{ DSMIXBIN_FRONT_RIGHT, DSBVOLUME_MAX}, // right channel
|
||||
{ DSMIXBIN_FRONT_CENTER, DSBVOLUME_MAX}, // left channel
|
||||
{ DSMIXBIN_FRONT_CENTER, DSBVOLUME_MAX}, // right channel
|
||||
{ DSMIXBIN_BACK_LEFT, DSBVOLUME_MAX}, // left channel
|
||||
{ DSMIXBIN_BACK_RIGHT, DSBVOLUME_MAX}, // right channel
|
||||
{ DSMIXBIN_LOW_FREQUENCY, DSBVOLUME_MAX}, // left channel
|
||||
{ DSMIXBIN_LOW_FREQUENCY, DSBVOLUME_MAX} // right channel
|
||||
{ DSMIXBIN_FRONT_LEFT, DSBVOLUME_MAX }, // left channel
|
||||
{ DSMIXBIN_FRONT_RIGHT, DSBVOLUME_MAX }, // right channel
|
||||
{ DSMIXBIN_FRONT_CENTER, DSBVOLUME_MAX }, // left channel
|
||||
{ DSMIXBIN_FRONT_CENTER, DSBVOLUME_MAX }, // right channel
|
||||
{ DSMIXBIN_BACK_LEFT, DSBVOLUME_MAX }, // left channel
|
||||
{ DSMIXBIN_BACK_RIGHT, DSBVOLUME_MAX }, // right channel
|
||||
{ DSMIXBIN_LOW_FREQUENCY, DSBVOLUME_MAX }, // left channel
|
||||
{ DSMIXBIN_LOW_FREQUENCY, DSBVOLUME_MAX } // right channel
|
||||
};
|
||||
DSMIXBINS dsmb;
|
||||
dsmb.dwMixBinCount = 8;
|
||||
@@ -262,7 +259,7 @@ CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
|
||||
format.lpwfxFormat = &waveformat;
|
||||
|
||||
HRESULT hr = ds.GetDS()->CreateSoundBuffer( &format, &buf, NULL );
|
||||
HRESULT hr = ds.GetDS()->CreateSoundBuffer( &format, &m_pBuffer, NULL );
|
||||
if( FAILED(hr) )
|
||||
return hr_ssprintf( hr, "CreateSoundBuffer failed" );
|
||||
|
||||
@@ -270,14 +267,14 @@ CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
/* I'm not sure this should ever be needed, but ... */
|
||||
DSBCAPS bcaps;
|
||||
bcaps.dwSize=sizeof(bcaps);
|
||||
hr = buf->GetCaps(&bcaps);
|
||||
hr = m_pBuffer->GetCaps( &bcaps );
|
||||
if( FAILED(hr) )
|
||||
return hr_ssprintf( hr, "buf->GetCaps" );
|
||||
if( int(bcaps.dwBufferBytes) != buffersize )
|
||||
return hr_ssprintf( hr, "m_pBuffer->GetCaps" );
|
||||
if( int(bcaps.dwBufferBytes) != m_iBufferSize )
|
||||
{
|
||||
LOG->Warn( "bcaps.dwBufferBytes (%i) != buffersize(%i); adjusting", bcaps.dwBufferBytes, buffersize );
|
||||
buffersize = bcaps.dwBufferBytes;
|
||||
writeahead = min( writeahead, buffersize );
|
||||
LOG->Warn( "bcaps.dwBufferBytes (%i) != m_iBufferSize(%i); adjusting", bcaps.dwBufferBytes, m_iBufferSize );
|
||||
m_iBufferSize = bcaps.dwBufferBytes;
|
||||
m_iWriteAhead = min( m_iWriteAhead, m_iBufferSize );
|
||||
}
|
||||
|
||||
if( !(bcaps.dwFlags & DSBCAPS_CTRLVOLUME) )
|
||||
@@ -286,70 +283,70 @@ CString DSoundBuf::Init( DSound &ds, DSoundBuf::hw hardware,
|
||||
LOG->Warn( "Sound channel missing DSBCAPS_GETCURRENTPOSITION2" );
|
||||
|
||||
DWORD got;
|
||||
hr = buf->GetFormat( &waveformat, sizeof(waveformat), &got );
|
||||
hr = m_pBuffer->GetFormat( &waveformat, sizeof(waveformat), &got );
|
||||
if( FAILED(hr) )
|
||||
LOG->Warn( hr_ssprintf(hr, "GetFormat on secondary buffer") );
|
||||
else if( (int) waveformat.nSamplesPerSec != samplerate )
|
||||
LOG->Warn( "Secondary buffer set to %i instead of %i", waveformat.nSamplesPerSec, samplerate );
|
||||
else if( (int) waveformat.nSamplesPerSec != m_iSampleRate )
|
||||
LOG->Warn( "Secondary buffer set to %i instead of %i", waveformat.nSamplesPerSec, m_iSampleRate );
|
||||
#endif
|
||||
|
||||
temp_buffer = new char[buffersize];
|
||||
m_pTempBuffer = new char[m_iBufferSize];
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void DSoundBuf::SetSampleRate(int hz)
|
||||
void DSoundBuf::SetSampleRate( int hz )
|
||||
{
|
||||
samplerate = hz;
|
||||
HRESULT hr = buf->SetFrequency( hz );
|
||||
m_iSampleRate = hz;
|
||||
HRESULT hr = m_pBuffer->SetFrequency( hz );
|
||||
if( FAILED(hr) )
|
||||
RageException::Throw( hr_ssprintf(hr, "buf->SetFrequency(%i)", hz) );
|
||||
RageException::Throw( hr_ssprintf(hr, "m_pBuffer->SetFrequency(%i)", hz) );
|
||||
}
|
||||
|
||||
void DSoundBuf::SetVolume(float vol)
|
||||
void DSoundBuf::SetVolume( float fVolume )
|
||||
{
|
||||
ASSERT(vol >= 0);
|
||||
ASSERT(vol <= 1);
|
||||
ASSERT( fVolume >= 0 );
|
||||
ASSERT( fVolume <= 1 );
|
||||
|
||||
if( vol == 0 )
|
||||
vol = 0.001f; // fix log10f(0) == -INF
|
||||
float vl2 = log10f(vol) / log10f(2); /* vol log 2 */
|
||||
if( fVolume == 0 )
|
||||
fVolume = 0.001f; // fix log10f(0) == -INF
|
||||
float iVolumeLog2 = log10f(fVolume) / log10f(2); /* vol log 2 */
|
||||
|
||||
/* Volume is a multiplier; SetVolume wants attenuation in hundredths of a decibel. */
|
||||
const int new_volume = max( int(1000 * vl2), DSBVOLUME_MIN );
|
||||
const int iNewVolume = max( int(1000 * iVolumeLog2), DSBVOLUME_MIN );
|
||||
|
||||
if( volume == new_volume )
|
||||
if( m_iVolume == iNewVolume )
|
||||
return;
|
||||
|
||||
HRESULT hr = buf->SetVolume( new_volume );
|
||||
HRESULT hr = m_pBuffer->SetVolume( iNewVolume );
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
static bool bWarned = false;
|
||||
if( !bWarned )
|
||||
LOG->Warn( hr_ssprintf(hr, "DirectSoundBuffer::SetVolume(%i) failed", volume) );
|
||||
LOG->Warn( hr_ssprintf(hr, "DirectSoundBuffer::SetVolume(%i) failed", iNewVolume) );
|
||||
bWarned = true;
|
||||
return;
|
||||
}
|
||||
|
||||
volume = new_volume;
|
||||
m_iVolume = iNewVolume;
|
||||
}
|
||||
|
||||
/* Determine if "pos" is between "start" and "end", for a circular buffer. Note that
|
||||
* a start/end pos is ambiguous when start == end; it can mean that the buffer is
|
||||
* completely full or completely empty; this function treats it as completely empty. */
|
||||
static bool contained( int start, int end, int pos )
|
||||
static bool contained( int iStart, int iEnd, int iPos )
|
||||
{
|
||||
if( end >= start ) /* start ... pos ... end */
|
||||
return start <= pos && pos < end;
|
||||
if( iEnd >= iStart ) /* iStart ... iPos ... iEnd */
|
||||
return iStart <= iPos && iPos < iEnd;
|
||||
else
|
||||
return pos >= start || pos < end;
|
||||
return iPos >= iStart || iPos < iEnd;
|
||||
}
|
||||
|
||||
DSoundBuf::~DSoundBuf()
|
||||
{
|
||||
if( buf != NULL )
|
||||
buf->Release();
|
||||
delete [] temp_buffer;
|
||||
if( m_pBuffer != NULL )
|
||||
m_pBuffer->Release();
|
||||
delete [] m_pTempBuffer;
|
||||
}
|
||||
|
||||
void round_up( int &i, int to )
|
||||
@@ -362,20 +359,20 @@ void round_up( int &i, int to )
|
||||
/* Check to make sure that, given the current writeahead and chunksize, we're
|
||||
* capable of filling the prefetch region entirely. If we aren't, increase
|
||||
* the writeahead. If this happens, we're underruning. */
|
||||
void DSoundBuf::CheckWriteahead( int cursorstart, int cursorend )
|
||||
void DSoundBuf::CheckWriteahead( int iCursorStart, int iCursorEnd )
|
||||
{
|
||||
/* If we're in a recovering-from-underrun state, stop. */
|
||||
if( extra_writeahead )
|
||||
if( m_iExtraWriteahead )
|
||||
return;
|
||||
|
||||
/* If the driver is requesting an unreasonably large prefetch, ignore it entirely.
|
||||
* Some drivers seem to give broken write cursors sporadically, requesting that
|
||||
* almost the entire buffer be filled. There's no reason a driver should ever need
|
||||
* more than 8k frames of writeahead. */
|
||||
int prefetch = cursorend - cursorstart;
|
||||
wrap( prefetch, buffersize );
|
||||
int iPrefetch = iCursorEnd - iCursorStart;
|
||||
wrap( iPrefetch, m_iBufferSize );
|
||||
|
||||
if( prefetch >= 1024*32 )
|
||||
if( iPrefetch >= 1024*32 )
|
||||
{
|
||||
static bool bLogged = false;
|
||||
if( bLogged )
|
||||
@@ -383,40 +380,40 @@ void DSoundBuf::CheckWriteahead( int cursorstart, int cursorend )
|
||||
bLogged = true;
|
||||
|
||||
LOG->Warn("Sound driver is requesting an overly large prefetch: wants %i (cursor at %i..%i), writeahead not adjusted",
|
||||
prefetch/bytes_per_frame(), cursorstart, cursorend );
|
||||
iPrefetch / bytes_per_frame(), iCursorStart, iCursorEnd );
|
||||
return;
|
||||
}
|
||||
|
||||
if( writeahead >= prefetch )
|
||||
if( m_iWriteAhead >= iPrefetch )
|
||||
return;
|
||||
|
||||
/* We need to increase the writeahead. */
|
||||
LOG->Trace("insufficient writeahead: wants %i (cursor at %i..%i), writeahead adjusted from %i to %i",
|
||||
prefetch/bytes_per_frame(), cursorstart, cursorend, writeahead, prefetch );
|
||||
iPrefetch / bytes_per_frame(), iCursorStart, iCursorEnd, m_iWriteAhead, iPrefetch );
|
||||
|
||||
writeahead = prefetch;
|
||||
m_iWriteAhead = iPrefetch;
|
||||
}
|
||||
|
||||
/* Figure out if we've underrun, and act if appropriate. */
|
||||
void DSoundBuf::CheckUnderrun( int cursorstart, int cursorend )
|
||||
void DSoundBuf::CheckUnderrun( int iCursorStart, int iCursorEnd )
|
||||
{
|
||||
/* If the buffer is full, we can't be underrunning. */
|
||||
if( buffer_bytes_filled >= buffersize )
|
||||
if( m_iBufferBytesFilled >= m_iBufferSize )
|
||||
return;
|
||||
|
||||
/* If nothing is expected to be filled, we can't underrun. */
|
||||
if( cursorstart == cursorend )
|
||||
if( iCursorStart == iCursorEnd )
|
||||
return;
|
||||
|
||||
/* If we're already in a recovering-from-underrun state, stop. */
|
||||
if( extra_writeahead )
|
||||
if( m_iExtraWriteahead )
|
||||
return;
|
||||
|
||||
int first_byte_filled = write_cursor-buffer_bytes_filled;
|
||||
wrap( first_byte_filled, buffersize );
|
||||
int iFirstByteFilled = m_iWriteCursor - m_iBufferBytesFilled;
|
||||
wrap( iFirstByteFilled, m_iBufferSize );
|
||||
|
||||
/* If the end of the play cursor has data, we haven't underrun. */
|
||||
if( buffer_bytes_filled > 0 && contained(first_byte_filled, write_cursor, cursorend) )
|
||||
if( m_iBufferBytesFilled > 0 && contained(iFirstByteFilled, m_iWriteCursor, iCursorEnd) )
|
||||
return;
|
||||
|
||||
/* Extend the writeahead to force fill as much as required to stop underrunning.
|
||||
@@ -425,67 +422,67 @@ void DSoundBuf::CheckUnderrun( int cursorstart, int cursorend )
|
||||
* the beat won't be lost, which is a lot easier to recover from in play. */
|
||||
/* XXX: If this happens repeatedly over a period of time, increase writeahead. */
|
||||
/* XXX: What was I doing here? This isn't working. We want to know the writeahead
|
||||
* value needed to fill from the current first_byte_filled all the way to cursorend. */
|
||||
// int needed_writeahead = (cursorstart + writeahead) - write_cursor;
|
||||
int needed_writeahead = cursorend - first_byte_filled;
|
||||
wrap( needed_writeahead, buffersize );
|
||||
if( needed_writeahead > writeahead )
|
||||
* value needed to fill from the current iFirstByteFilled all the way to iCursorEnd. */
|
||||
// int iNeededWriteahead = (iCursorStart + writeahead) - m_iWriteCursor;
|
||||
int iNeededWriteahead = iCursorEnd - iFirstByteFilled;
|
||||
wrap( iNeededWriteahead, m_iBufferSize );
|
||||
if( iNeededWriteahead > m_iWriteAhead )
|
||||
{
|
||||
extra_writeahead = needed_writeahead - writeahead;
|
||||
writeahead = needed_writeahead;
|
||||
m_iExtraWriteahead = iNeededWriteahead - m_iWriteAhead;
|
||||
m_iWriteAhead = iNeededWriteahead;
|
||||
}
|
||||
|
||||
int missed_by = cursorend - write_cursor;
|
||||
wrap( missed_by, buffersize );
|
||||
int iMissedBy = iCursorEnd - m_iWriteCursor;
|
||||
wrap( iMissedBy, m_iBufferSize );
|
||||
|
||||
CString s = ssprintf( "underrun: %i..%i (%i) filled but cursor at %i..%i; missed it by %i",
|
||||
first_byte_filled, write_cursor, buffer_bytes_filled, cursorstart, cursorend, missed_by );
|
||||
iFirstByteFilled, m_iWriteCursor, m_iBufferBytesFilled, iCursorStart, iCursorEnd, iMissedBy );
|
||||
|
||||
if( extra_writeahead )
|
||||
s += ssprintf( "; extended writeahead by %i to %i", extra_writeahead, writeahead );
|
||||
if( m_iExtraWriteahead )
|
||||
s += ssprintf( "; extended writeahead by %i to %i", m_iExtraWriteahead, m_iWriteAhead );
|
||||
|
||||
s += "; last: ";
|
||||
for( int i = 0; i < 4; ++i )
|
||||
s += ssprintf( "%i, %i; ", last_cursors[i][0], last_cursors[i][1] );
|
||||
s += ssprintf( "%i, %i; ", m_iLastCursors[i][0], m_iLastCursors[i][1] );
|
||||
|
||||
LOG->Trace( "%s", s.c_str() );
|
||||
}
|
||||
|
||||
bool DSoundBuf::get_output_buf( char **buffer, unsigned *bufsiz, int chunksize )
|
||||
bool DSoundBuf::get_output_buf( char **pBuffer, unsigned *pBufferSize, int iChunksize )
|
||||
{
|
||||
ASSERT(!buffer_locked);
|
||||
ASSERT( !m_bBufferLocked );
|
||||
|
||||
chunksize *= bytes_per_frame();
|
||||
iChunksize *= bytes_per_frame();
|
||||
|
||||
DWORD cursorstart, cursorend;
|
||||
DWORD iCursorStart, iCursorEnd;
|
||||
|
||||
HRESULT result;
|
||||
|
||||
/* It's easiest to think of the cursor as a block, starting and ending at
|
||||
* the two values returned by GetCurrentPosition, that we can't write to. */
|
||||
result = buf->GetCurrentPosition( &cursorstart, &cursorend );
|
||||
result = m_pBuffer->GetCurrentPosition( &iCursorStart, &iCursorEnd );
|
||||
#ifndef _XBOX
|
||||
if ( result == DSERR_BUFFERLOST )
|
||||
if( result == DSERR_BUFFERLOST )
|
||||
{
|
||||
buf->Restore();
|
||||
result = buf->GetCurrentPosition( &cursorstart, &cursorend );
|
||||
m_pBuffer->Restore();
|
||||
result = m_pBuffer->GetCurrentPosition( &iCursorStart, &iCursorEnd );
|
||||
}
|
||||
if ( result != DS_OK )
|
||||
if( result != DS_OK )
|
||||
{
|
||||
LOG->Warn( hr_ssprintf(result, "DirectSound::GetCurrentPosition failed") );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
memmove( &last_cursors[0][0], &last_cursors[1][0], sizeof(int)*6 );
|
||||
last_cursors[3][0] = cursorstart;
|
||||
last_cursors[3][1] = cursorend;
|
||||
memmove( &m_iLastCursors[0][0], &m_iLastCursors[1][0], sizeof(int)*6 );
|
||||
m_iLastCursors[3][0] = iCursorStart;
|
||||
m_iLastCursors[3][1] = iCursorEnd;
|
||||
|
||||
/* Some cards (Creative AudioPCI) have a no-write area even when not playing. I'm not
|
||||
* sure what that means, but it breaks the assumption that we can fill the whole writeahead
|
||||
* when prebuffering. */
|
||||
if( !playing )
|
||||
cursorend = cursorstart;
|
||||
if( !m_bPlaying )
|
||||
iCursorEnd = iCursorStart;
|
||||
|
||||
/*
|
||||
* Some cards (Game Theater XP 7.1 hercwdm.sys 5.12.01.4101 [466688b, 01-10-2003])
|
||||
@@ -506,155 +503,155 @@ bool DSoundBuf::get_output_buf( char **buffer, unsigned *bufsiz, int chunksize )
|
||||
* (We can't; we have no idea what the cursors actually are.)
|
||||
*/
|
||||
{
|
||||
int prefetch = cursorend - cursorstart;
|
||||
wrap( prefetch, buffersize );
|
||||
int iPrefetch = iCursorEnd - iCursorStart;
|
||||
wrap( iPrefetch, m_iBufferSize );
|
||||
|
||||
if( buffersize-prefetch < 1024*4 )
|
||||
if( m_iBufferSize - iPrefetch < 1024*4 )
|
||||
{
|
||||
LOG->Trace( "Strange DirectSound cursor ignored: %i..%i", cursorstart, cursorend );
|
||||
LOG->Trace( "Strange DirectSound cursor ignored: %i..%i", iCursorStart, iCursorEnd );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update buffer_bytes_filled. */
|
||||
/* Update m_iBufferBytesFilled. */
|
||||
{
|
||||
int first_byte_filled = write_cursor-buffer_bytes_filled;
|
||||
wrap( first_byte_filled, buffersize );
|
||||
int iFirstByteFilled = m_iWriteCursor - m_iBufferBytesFilled;
|
||||
wrap( iFirstByteFilled, m_iBufferSize );
|
||||
|
||||
/* The number of bytes that have been played since the last time we got here: */
|
||||
int bytes_played = cursorstart - first_byte_filled;
|
||||
wrap( bytes_played, buffersize );
|
||||
int bytes_played = iCursorStart - iFirstByteFilled;
|
||||
wrap( bytes_played, m_iBufferSize );
|
||||
|
||||
buffer_bytes_filled -= bytes_played;
|
||||
buffer_bytes_filled = max( 0, buffer_bytes_filled );
|
||||
m_iBufferBytesFilled -= bytes_played;
|
||||
m_iBufferBytesFilled = max( 0, m_iBufferBytesFilled );
|
||||
|
||||
if( extra_writeahead )
|
||||
if( m_iExtraWriteahead )
|
||||
{
|
||||
int used = min( extra_writeahead, bytes_played );
|
||||
CString s = ssprintf("used %i of %i (%i..%i)", used, extra_writeahead, cursorstart, cursorend );
|
||||
int used = min( m_iExtraWriteahead, bytes_played );
|
||||
CString s = ssprintf("used %i of %i (%i..%i)", used, m_iExtraWriteahead, iCursorStart, iCursorEnd );
|
||||
s += "; last: ";
|
||||
for( int i = 0; i < 4; ++i )
|
||||
s += ssprintf( "%i, %i; ", last_cursors[i][0], last_cursors[i][1] );
|
||||
s += ssprintf( "%i, %i; ", m_iLastCursors[i][0], m_iLastCursors[i][1] );
|
||||
LOG->Trace("%s", s.c_str());
|
||||
writeahead -= used;
|
||||
extra_writeahead -= used;
|
||||
m_iWriteAhead -= used;
|
||||
m_iExtraWriteahead -= used;
|
||||
}
|
||||
}
|
||||
|
||||
CheckWriteahead( cursorstart, cursorend );
|
||||
CheckUnderrun( cursorstart, cursorend );
|
||||
CheckWriteahead( iCursorStart, iCursorEnd );
|
||||
CheckUnderrun( iCursorStart, iCursorEnd );
|
||||
|
||||
/* If we already have enough bytes written ahead, stop. */
|
||||
if( buffer_bytes_filled > writeahead )
|
||||
if( m_iBufferBytesFilled > m_iWriteAhead )
|
||||
return false;
|
||||
|
||||
int num_bytes_empty = writeahead-buffer_bytes_filled;
|
||||
int iNumBytesEmpty = m_iWriteAhead - m_iBufferBytesFilled;
|
||||
|
||||
/* num_bytes_empty is the amount of free buffer space. If it's
|
||||
* too small, come back later. */
|
||||
if( num_bytes_empty < chunksize )
|
||||
if( iNumBytesEmpty < iChunksize )
|
||||
return false;
|
||||
|
||||
// LOG->Trace("gave %i at %i (%i, %i) %i filled", num_bytes_empty, write_cursor, cursor, write, buffer_bytes_filled);
|
||||
// LOG->Trace("gave %i at %i (%i, %i) %i filled", iNumBytesEmpty, m_iWriteCursor, cursor, write, m_iBufferBytesFilled);
|
||||
|
||||
/* Lock the audio buffer. */
|
||||
result = buf->Lock( write_cursor, num_bytes_empty, (LPVOID *)&locked_buf1, (DWORD *) &locked_size1, (LPVOID *)&locked_buf2, (DWORD *) &locked_size2, 0 );
|
||||
result = m_pBuffer->Lock( m_iWriteCursor, iNumBytesEmpty, (LPVOID *) &m_pLockedBuf1, (DWORD *) &m_iLockedSize1, (LPVOID *) &m_pLockedBuf2, (DWORD *) &m_iLockedSize2, 0 );
|
||||
|
||||
#ifndef _XBOX
|
||||
if ( result == DSERR_BUFFERLOST )
|
||||
if( result == DSERR_BUFFERLOST )
|
||||
{
|
||||
buf->Restore();
|
||||
result = buf->Lock( write_cursor, num_bytes_empty, (LPVOID *)&locked_buf1, (DWORD *) &locked_size1, (LPVOID *)&locked_buf2, (DWORD *) &locked_size2, 0 );
|
||||
m_pBuffer->Restore();
|
||||
result = m_pBuffer->Lock( m_iWriteCursor, iNumBytesEmpty, (LPVOID *) &m_pLockedBuf1, (DWORD *) &m_iLockedSize1, (LPVOID *) &m_pLockedBuf2, (DWORD *) &m_iLockedSize2, 0 );
|
||||
}
|
||||
#endif
|
||||
if ( result != DS_OK )
|
||||
if( result != DS_OK )
|
||||
{
|
||||
LOG->Warn( hr_ssprintf(result, "Couldn't lock the DirectSound buffer.") );
|
||||
return false;
|
||||
}
|
||||
|
||||
*buffer = temp_buffer;
|
||||
*bufsiz = locked_size1 + locked_size2;
|
||||
*pBuffer = m_pTempBuffer;
|
||||
*pBufferSize = m_iLockedSize1 + m_iLockedSize2;
|
||||
|
||||
write_cursor += num_bytes_empty;
|
||||
if( write_cursor >= buffersize )
|
||||
write_cursor -= buffersize;
|
||||
m_iWriteCursor += iNumBytesEmpty;
|
||||
if( m_iWriteCursor >= m_iBufferSize )
|
||||
m_iWriteCursor -= m_iBufferSize;
|
||||
|
||||
buffer_bytes_filled += num_bytes_empty;
|
||||
write_cursor_pos += num_bytes_empty / bytes_per_frame();
|
||||
m_iBufferBytesFilled += iNumBytesEmpty;
|
||||
m_iWriteCursorPos += iNumBytesEmpty / bytes_per_frame();
|
||||
|
||||
buffer_locked = true;
|
||||
m_bBufferLocked = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSoundBuf::release_output_buf( char *buffer, unsigned bufsiz )
|
||||
void DSoundBuf::release_output_buf( char *pBuffer, unsigned iBufferSize )
|
||||
{
|
||||
memcpy( locked_buf1, buffer, locked_size1 );
|
||||
memcpy( locked_buf2, buffer+locked_size1, locked_size2 );
|
||||
buf->Unlock( locked_buf1, locked_size1, locked_buf2, locked_size2 );
|
||||
buffer_locked = false;
|
||||
memcpy( m_pLockedBuf1, pBuffer, m_iLockedSize1 );
|
||||
memcpy( m_pLockedBuf2, pBuffer+m_iLockedSize1, m_iLockedSize2 );
|
||||
m_pBuffer->Unlock( m_pLockedBuf1, m_iLockedSize1, m_pLockedBuf2, m_iLockedSize2 );
|
||||
m_bBufferLocked = false;
|
||||
}
|
||||
|
||||
int64_t DSoundBuf::GetPosition() const
|
||||
{
|
||||
DWORD cursor, junk;
|
||||
HRESULT hr = buf->GetCurrentPosition( &cursor, &junk );
|
||||
DWORD iCursor, iJunk;
|
||||
HRESULT hr = m_pBuffer->GetCurrentPosition( &iCursor, &iJunk );
|
||||
ASSERT_M( SUCCEEDED(hr), hr_ssprintf(hr, "GetCurrentPosition") );
|
||||
|
||||
/* This happens occasionally on "Realtek AC97 Audio". */
|
||||
if( (int) cursor == buffersize )
|
||||
cursor = 0;
|
||||
ASSERT_M( (int) cursor < buffersize, ssprintf("%i, %i", cursor, buffersize) );
|
||||
if( (int) iCursor == m_iBufferSize )
|
||||
iCursor = 0;
|
||||
ASSERT_M( (int) iCursor < m_iBufferSize, ssprintf("%i, %i", iCursor, m_iBufferSize) );
|
||||
|
||||
int cursor_frames = int(cursor) / bytes_per_frame();
|
||||
int write_cursor_frames = write_cursor / bytes_per_frame();
|
||||
int iCursorFrames = int(iCursor) / bytes_per_frame();
|
||||
int iWriteCursorFrames = m_iWriteCursor / bytes_per_frame();
|
||||
|
||||
int frames_behind = write_cursor_frames - cursor_frames;
|
||||
/* frames_behind will be 0 if we're called before the buffer starts playing:
|
||||
* both write_cursor_frames and cursor_frames will be 0. */
|
||||
if( frames_behind < 0 )
|
||||
frames_behind += buffersize_frames(); /* unwrap */
|
||||
int iFramesBehind = iWriteCursorFrames - iCursorFrames;
|
||||
/* iFramesBehind will be 0 if we're called before the buffer starts playing:
|
||||
* both iWriteCursorFrames and iCursorFrames will be 0. */
|
||||
if( iFramesBehind < 0 )
|
||||
iFramesBehind += buffersize_frames(); /* unwrap */
|
||||
|
||||
int64_t ret = write_cursor_pos - frames_behind;
|
||||
int64_t iRet = m_iWriteCursorPos - iFramesBehind;
|
||||
|
||||
/* Failsafe: never return a value smaller than we've already returned.
|
||||
* This can happen once in a while in underrun conditions. */
|
||||
ret = max( LastPosition, ret );
|
||||
LastPosition = ret;
|
||||
iRet = max( m_iLastPosition, iRet );
|
||||
m_iLastPosition = iRet;
|
||||
|
||||
return ret;
|
||||
return iRet;
|
||||
}
|
||||
|
||||
void DSoundBuf::Play()
|
||||
{
|
||||
if( playing )
|
||||
if( m_bPlaying )
|
||||
return;
|
||||
buf->Play( 0, 0, DSBPLAY_LOOPING );
|
||||
playing = true;
|
||||
m_pBuffer->Play( 0, 0, DSBPLAY_LOOPING );
|
||||
m_bPlaying = true;
|
||||
}
|
||||
|
||||
void DSoundBuf::Stop()
|
||||
{
|
||||
if( !playing )
|
||||
if( !m_bPlaying )
|
||||
return;
|
||||
|
||||
buf->Stop();
|
||||
buf->SetCurrentPosition(0);
|
||||
m_pBuffer->Stop();
|
||||
m_pBuffer->SetCurrentPosition(0);
|
||||
|
||||
write_cursor_pos = write_cursor = buffer_bytes_filled = 0;
|
||||
LastPosition = 0;
|
||||
m_iWriteCursorPos = m_iWriteCursor = m_iBufferBytesFilled = 0;
|
||||
m_iLastPosition = 0;
|
||||
|
||||
writeahead -= extra_writeahead;
|
||||
extra_writeahead = 0;
|
||||
m_iWriteAhead -= m_iExtraWriteahead;
|
||||
m_iExtraWriteahead = 0;
|
||||
|
||||
/* When stopped and rewound, the play and write cursors should both be 0. */
|
||||
/* This isn't true on some broken cards. */
|
||||
// DWORD play, write;
|
||||
// buf->GetCurrentPosition( &play, &write );
|
||||
// ASSERT_M( play == 0 && write == 0, ssprintf("%i, %i", play, write) );
|
||||
// DWORD iPlay, iWrite;
|
||||
// m_pBuffer->GetCurrentPosition( &iPlay, &iWrite );
|
||||
// ASSERT_M( iPlay == 0 && iWrite == 0, ssprintf("%i, %i", iPlay, iWrite) );
|
||||
|
||||
playing = false;
|
||||
m_bPlaying = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,18 +11,19 @@ struct IDirectSoundBuffer;
|
||||
|
||||
class DSound
|
||||
{
|
||||
IDirectSound *ds;
|
||||
static BOOL CALLBACK EnumCallback( LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext);
|
||||
|
||||
void SetPrimaryBufferMode();
|
||||
|
||||
public:
|
||||
IDirectSound *GetDS() const { return ds; }
|
||||
IDirectSound *GetDS() const { return m_pDS; }
|
||||
bool IsEmulated() const;
|
||||
|
||||
DSound();
|
||||
~DSound();
|
||||
CString Init();
|
||||
|
||||
private:
|
||||
IDirectSound *m_pDS;
|
||||
static BOOL CALLBACK EnumCallback( LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext);
|
||||
|
||||
void SetPrimaryBufferMode();
|
||||
};
|
||||
|
||||
class DSoundBuf
|
||||
@@ -36,47 +37,47 @@ public:
|
||||
|
||||
DSoundBuf();
|
||||
CString Init( DSound &ds, hw hardware,
|
||||
int channels, int samplerate, int samplebits, int writeahead );
|
||||
int iChannels, int iSampleRate, int iSampleBits, int iWriteAhead );
|
||||
|
||||
bool get_output_buf(char **buffer, unsigned *bufsiz, int chunksize);
|
||||
void release_output_buf(char *buffer, unsigned bufsiz);
|
||||
bool get_output_buf( char **pBuffer, unsigned *iBuffersize, int iChunksize );
|
||||
void release_output_buf( char *pBuffer, unsigned iBuffersize );
|
||||
|
||||
void Play();
|
||||
void Stop();
|
||||
void SetVolume(float vol);
|
||||
void SetSampleRate(int hz);
|
||||
int GetSampleRate() { return samplerate; }
|
||||
void SetVolume( float fVolume );
|
||||
void SetSampleRate( int iRate );
|
||||
int GetSampleRate() const { return m_iSampleRate; }
|
||||
|
||||
~DSoundBuf();
|
||||
int64_t GetPosition() const;
|
||||
int64_t GetOutputPosition() const { return write_cursor_pos; }
|
||||
int64_t GetOutputPosition() const { return m_iWriteCursorPos; }
|
||||
|
||||
private:
|
||||
int buffersize_frames() const { return buffersize / bytes_per_frame(); }
|
||||
int bytes_per_frame() const { return channels*samplebits/8; }
|
||||
int buffersize_frames() const { return m_iBufferSize / bytes_per_frame(); }
|
||||
int bytes_per_frame() const { return m_iChannels*m_iSampleBits/8; }
|
||||
|
||||
void CheckWriteahead( int cursorstart, int cursorend );
|
||||
void CheckUnderrun( int cursorstart, int cursorend );
|
||||
void CheckWriteahead( int iCursorStart, int iCursorEnd );
|
||||
void CheckUnderrun( int iCursorStart, int iCursorEnd );
|
||||
|
||||
IDirectSoundBuffer *buf;
|
||||
IDirectSoundBuffer *m_pBuffer;
|
||||
|
||||
int channels, samplerate, samplebits, writeahead;
|
||||
int volume;
|
||||
int m_iChannels, m_iSampleRate, m_iSampleBits, m_iWriteAhead;
|
||||
int m_iVolume;
|
||||
|
||||
int buffersize;
|
||||
int m_iBufferSize;
|
||||
|
||||
int write_cursor, buffer_bytes_filled; /* bytes */
|
||||
int extra_writeahead;
|
||||
int64_t write_cursor_pos; /* frames */
|
||||
mutable int64_t LastPosition;
|
||||
bool playing;
|
||||
int m_iWriteCursor, m_iBufferBytesFilled; /* bytes */
|
||||
int m_iExtraWriteahead;
|
||||
int64_t m_iWriteCursorPos; /* frames */
|
||||
mutable int64_t m_iLastPosition;
|
||||
bool m_bPlaying;
|
||||
|
||||
bool buffer_locked;
|
||||
char *locked_buf1, *locked_buf2;
|
||||
int locked_size1, locked_size2;
|
||||
char *temp_buffer;
|
||||
bool m_bBufferLocked;
|
||||
char *m_pLockedBuf1, *m_pLockedBuf2;
|
||||
int m_iLockedSize1, m_iLockedSize2;
|
||||
char *m_pTempBuffer;
|
||||
|
||||
int last_cursors[4][2];
|
||||
int m_iLastCursors[4][2];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user