📄 dsapi.cpp
字号:
* pointer forward until we've read the file enough times
* to fill the buffer. NOTE: It's probably not efficient
* to bother with the overhead of streaming a file that's
* not at least as large as the buffer... */
lpTemp += uChkErr;
dwLen1 -= uChkErr;
nChkErr = WaveStartDataRead( &lpwiWave->hmmio,
&lpwiWave->mmck,
&lpwiWave->mmckInRIFF );
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen1,
lpTemp,
&lpwiWave->mmck, &uChkErr );
} while( uChkErr < dwLen1 );
}
else
{
lpwiWave->bFoundEnd = TRUE;
lpwiWave->nRemainingSegments = (int)(uChkErr /
lpwiWave->dwBufferSegSize);
// DPF( 3,"Setting bFoundEnd in load, nRemSegs = %i, dwBuffSegSize = %u",
// lpwiWave->nRemainingSegments, lpwiWave->dwBufferSegSize );
memset( (lpWrite1+uChkErr),
lpwiWave->pwfx->wBitsPerSample == 8 ? 128 : 0,
(dwLen1 - uChkErr));
}
}
}
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[nIndex] == lpwiWave );
#endif
dsRetVal = lpwiWave->lpDSBStreamBuffer->Unlock( (LPVOID)lpWrite1, dwLen1,
(LPVOID)lpWrite2, 0 );
#ifdef __TEST_SOUND__
ASSERT( lpwiWave->lpDSBStreamBuffer );
#endif
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[nIndex] == lpwiWave );
#endif
lpwiWave->dwNextWriteOffset = lpwiWave->dwPlayLast = lpwiWave->dwProgress = 0;
lpwiWave->bDonePlaying = FALSE;
lpwiWave->bLoopFile = FALSE;
#ifdef __TEST_SOUND__
ASSERT( lpwiWave->lpDSBStreamBuffer );
#endif
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[nIndex] == lpwiWave );
#endif
// LPARAM : if it is dynamic wave object
SendMessage( DS_hwndGame, WM_DSSTREAM_PROGRESS, 0L, 0L );
nChkErr = 0;
END_SETUP:
return( nChkErr );
}
/*****************************************************************************/
/* StreamBufferRelease() */
/* */
/* close Stream wave file, and kill timer if nessacary. */
/* */
/*****************************************************************************/
// nIndex : ID in global wave array
void StreamBufferRelease( int nIndex )
{
LPWAVEDYNAMIC lpwiWave = NULL;
// set lpwdWaves[nIndex] to lpwiWave
// so that you can use lpwiWave directly
lpwiWave = SetToGlobal( nIndex );
WaveCloseReadFile( &lpwiWave->hmmio, &lpwiWave->pwfx );
#ifdef __TEST_SOUND__
ASSERT( lpwiWave->lpDSBStreamBuffer );
#endif
if( lpwiWave->lpDSBStreamBuffer )
lpwiWave->lpDSBStreamBuffer->Release();
lpwiWave->lpDSBStreamBuffer = NULL;
}
/*****************************************************************************/
/* ResetWavePlayer() */
/* */
/* Performs a subset of the above operations (in StreamBufferSetup). Things */
/* not done include creating a DSB and opening the file (it's already open). */
/* */
/*****************************************************************************/
// nIndex : ID in global wave array
void ResetWavePlayer( int nIndex )
{
LPBYTE lpWrite1, lpWrite2;
DWORD dwLen1, dwLen2;
UINT uChkErr;
int nChkErr;
HRESULT dsrval;
LPWAVEDYNAMIC lpwiWave = NULL;
// set lpwdWaves[nIndex] to lpwiWave
// so that you can use lpwiWave directly
lpwiWave = SetToGlobal( nIndex );
WaveStartDataRead( &lpwiWave->hmmio, &lpwiWave->mmck, &lpwiWave->mmckInRIFF );
lpwiWave->bFoundEnd = FALSE;
lpwiWave->nRemainingSegments = 0;
dsrval = lpwiWave->lpDSBStreamBuffer->Lock( 0, lpwiWave->dwBufferSize,
(void**)&lpWrite1, &dwLen1,
(void**)&lpWrite2, &dwLen2,
0 );
if( dsrval != DS_OK )
{
char errStr[129];
switch ( dsrval )
{
case DSERR_BUFFERLOST:
strcpy(errStr, "DSERR_BUFFERLOST" );
break;
case DSERR_INVALIDPARAM:
strcpy(errStr, "DSERR_INVALIDPARAM" );
break;
case DSERR_INVALIDCALL:
strcpy(errStr, "DSERR_INVALIDCALL" );
break;
case DSERR_PRIOLEVELNEEDED:
strcpy(errStr, "DSERR_PRIOLEVELNEEDED" );
break;
}
strcat( errStr, "\n" );
//OutputDebugString( "TimeFunc() could not lock DirectSoundBuffer" );
OutputDebugString( errStr );
return;
}
if( dwLen1 )
{
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen1, lpWrite1,
&lpwiWave->mmck, &uChkErr );
if( uChkErr < dwLen1 )
{
if( lpwiWave->bLoopFile )
{
/* If the file is shorter than the buffer and we're looping, we need to
* read the file in again so that we don't get a block of silence before
* the timer loops playback.
*/
LPBYTE lpTemp = lpWrite1;
do
{
/* Continue decrementing our count and moving our temp
* pointer forward until we've read the file enough times
* to fill the buffer. NOTE: It's probably not efficient
* to bother with the overhead of streaming a file that's
* not at least as large as the buffer... */
lpTemp += uChkErr;
dwLen1 -= uChkErr;
nChkErr = WaveStartDataRead( &lpwiWave->hmmio,
&lpwiWave->mmck,
&lpwiWave->mmckInRIFF );
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen1,
lpTemp,
&lpwiWave->mmck, &uChkErr );
} while( uChkErr < dwLen1 );
}
else
{
lpwiWave->bFoundEnd = TRUE;
lpwiWave->nRemainingSegments = (int)(uChkErr / lpwiWave->dwBufferSegSize);
// DPF( 3,"Setting bFoundEnd in load, nRemSegs = %i, dwBuffSegSize = %u",
// lpwiWave->nRemainingSegments, lpwiWave->dwBufferSegSize );
// Cover ourselves by filling the rest of the buffer space
// with 8 or 16 bit silence, in case we can't stop the playback
// exactly on a block boundary and we run a bit into NULL data
memset(( lpWrite1 + uChkErr),
lpwiWave->pwfx->wBitsPerSample == 8 ? 128 : 0,
dwLen1 - uChkErr);
}
}
}
dsrval = lpwiWave->lpDSBStreamBuffer->Unlock( (LPVOID)lpWrite1, dwLen1,
(LPVOID)lpWrite2, 0 );
lpwiWave->dwNextWriteOffset = lpwiWave->dwPlayLast = lpwiWave->dwProgress = 0;
lpwiWave->bDonePlaying = FALSE;
// LPARAM : 0 if it is dynamic wave object
SendMessage( DS_hwndGame, WM_DSSTREAM_PROGRESS, 0L, 0L );
}
// nIndex : ID in global wave array
void CALLBACK TimeFunc( UINT uTimerID, UINT uMsg, DWORD dwUser,
DWORD dw1, DWORD dw2 )
{
static bInTimer = FALSE;
LPBYTE lpWrite1, lpWrite2, lpTemp;
DWORD dwLen1, dwLen2, dwPlay, dwWrite;
int nChkErr;
UINT uChkErr;
HRESULT dsrval;
LPWAVEDYNAMIC lpwiWave = NULL;
if( bInTimer )
{
return;
}
else
{
bInTimer = TRUE;
}
WaitForSingleObject( hMutex, INFINITE );
// set lpwdWaves[nIndex] to lpwiWave
// so that you can use lpwiWave directly
lpwiWave = SetToGlobal( dwUser );
// very rarely to meet this situation
// if the thread is stoping the wave, and this function begin to wait,
// when stoped, the dwUser is invalid, and lpwiWave is invalid too.
// so must test if should quit.
if( !lpwiWave )
{
OutputDebugString( "DS dynamic error: just begin to play when stop wave!\n" );
//-----debug
#ifdef _DS_LOG_
FILE*fp=fopen( "DSTest.log","at" );
fprintf(fp,"A" );
fclose(fp);
#endif
//-----debug
goto END_TIME;
}
#ifdef __TEST_SOUND__
ASSERT( lpwiWave->uTimerID == uTimerID );
#endif
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
/* Get and print the current position of the play cursor */
lpwiWave->lpDSBStreamBuffer->GetCurrentPosition( &dwPlay, &dwWrite );
if(( lpwiWave->dwNextWriteOffset < dwPlay )
&& (( lpwiWave->dwNextWriteOffset + lpwiWave->dwBufferSegSize ) > dwPlay ))
{
/* OutputDebugString( "DS dynamic error: Write offset!\n" );
//-----debug
FILE*fp=fopen( "DSTest.log","at" );
fprintf(fp,"B" );
fclose(fp);
//-----debug
*/
goto END_TIME;
}
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
/* Have we found the end of the file and passed the buffer end? */
if( lpwiWave->bFoundEnd && !lpwiWave->nRemainingSegments )
{
if( !lpwiWave->bDonePlaying )
{
PostMessage( DS_hwndGame, WM_DSSTREAM_DONE, (WPARAM)lpwiWave->nID, (LPARAM)0 );
//lpwiWave->bDonePlaying = TRUE;
lpwiWave->Stop();
}
goto END_TIME;
}
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
if( dwPlay < lpwiWave->dwPlayLast )
lpwiWave->dwProgress += (dwPlay + lpwiWave->dwBufferSize - lpwiWave->dwPlayLast);
else
lpwiWave->dwProgress += (dwPlay - lpwiWave->dwPlayLast);
lpwiWave->dwPlayLast = dwPlay;
PostMessage( DS_hwndGame, WM_DSSTREAM_PROGRESS, 0L, 0L );
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
/*
* If lpwiWave->bFoundEnd == TRUE, then we've finished reading in the file,
* but we need to wait until the buffer's play cursor passes the point we
* were at when we found out we were done reading.
*/
if( lpwiWave->bFoundEnd && lpwiWave->nRemainingSegments )
{
lpwiWave->nRemainingSegments--;
if( lpwiWave->nRemainingSegments > 1 ) {
dsrval = lpwiWave->lpDSBStreamBuffer->Lock( lpwiWave->dwNextWriteOffset,
lpwiWave->dwBufferSegSize,
(void**)&lpWrite1, &dwLen1,
(void**)&lpWrite2, &dwLen2,
0 );
if( dsrval != DS_OK )
{
char errStr[129];
switch ( dsrval )
{
case DSERR_BUFFERLOST:
strcpy(errStr, "DSERR_BUFFERLOST" );
break;
case DSERR_INVALIDPARAM:
strcpy(errStr, "DSERR_INVALIDPARAM" );
break;
case DSERR_INVALIDCALL:
strcpy(errStr, "DSERR_INVALIDCALL" );
break;
case DSERR_PRIOLEVELNEEDED:
strcpy(errStr, "DSERR_PRIOLEVELNEEDED" );
break;
}
strcat( errStr, "\n" );
//OutputDebugString( "TimeFunc() could not lock DirectSoundBuffer" );
//-----debug
#ifdef _DS_LOG_
FILE*fp=fopen( "DSTest.log","at" );
fprintf(fp,"C" );
fclose(fp);
#endif
//-----debug
OutputDebugString( errStr );
goto END_TIME;
}
if( lpwiWave->pwfx->wBitsPerSample == 8 )
memset( lpWrite1, 128, dwLen1 );
else if( lpwiWave->pwfx->wBitsPerSample == 16 )
memset( lpWrite1, 0, dwLen1 );
lpwiWave->lpDSBStreamBuffer->Unlock( (LPVOID)lpWrite1, dwLen1,
(LPVOID)lpWrite2, dwLen2 );
/*
* This code is stolen from the end of the routine -- we need to keep
* zeroing out buffer segments while we're waiting for the play cursor to
* catch up to the end of the WAVE data.
*/
lpwiWave->dwNextWriteOffset += lpwiWave->dwBufferSegSize;
if( lpwiWave->dwNextWriteOffset >= lpwiWave->dwBufferSize )
lpwiWave->dwNextWriteOffset -= lpwiWave->dwBufferSize;
}
goto END_TIME;
}
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
/* Lock a segment of memory that is behind the play cursor */
if( ( dsrval = lpwiWave->lpDSBStreamBuffer->Lock( lpwiWave->dwNextWriteOffset,
lpwiWave->dwBufferSegSize,
(void**)&lpWrite1, &dwLen1,
(void**)&lpWrite2, &dwLen2,
0 ) ) != DS_OK )
{
char errStr[129];
switch ( dsrval )
{
case DSERR_BUFFERLOST:
strcpy(errStr, "DSERR_BUFFERLOST" );
break;
case DSERR_INVALIDPARAM:
strcpy(errStr, "DSERR_INVALIDPARAM" );
break;
case DSERR_INVALIDCALL:
strcpy(errStr, "DSERR_INVALIDCALL" );
break;
case DSERR_PRIOLEVELNEEDED:
strcpy(errStr, "DSERR_PRIOLEVELNEEDED" );
break;
}
strcat( errStr, "\n" );
//OutputDebugString( "TimeFunc() could not lock DirectSoundBuffer" );
//-----debug
#ifdef _DS_LOG_
FILE*fp=fopen( "DSTest.log","at" );
fprintf(fp,"D" );
fclose(fp);
#endif
//-----debug
OutputDebugString( errStr );
goto END_TIME;
}
#ifdef __TEST_SOUND__
ASSERT( lpwdWaves[dwUser] == lpwiWave );
#endif
if( dwLen1 && !lpwiWave->bDonePlaying )
{
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen1, lpWrite1,
&lpwiWave->mmck, &uChkErr );
if( uChkErr < (UINT)dwLen1 )
{
if( !lpwiWave->bLoopFile )
{
/* Zero out the rest of this block */
if( lpwiWave->pwfx->wBitsPerSample == 8 )
memset( lpWrite1+uChkErr, 128, ((UINT)dwLen1-uChkErr));
else if( lpwiWave->pwfx->wBitsPerSample == 16 )
memset( lpWrite1+uChkErr, 0, ((UINT)dwLen1-uChkErr));
/* Enable play completion detection code at the beginning of the next call */
lpwiWave->bFoundEnd = TRUE;
if( dwPlay > lpwiWave->dwNextWriteOffset )
lpwiWave->nRemainingSegments = (lpwiWave->dwNextWriteOffset
+ lpwiWave->dwBufferSize - dwPlay)
/ lpwiWave->dwBufferSegSize;
else
lpwiWave->nRemainingSegments = (lpwiWave->dwNextWriteOffset
- dwPlay)
/ lpwiWave->dwBufferSegSize;
}
else
{
lpTemp = lpWrite1;
do
{
/* Continue decrementing our count and moving our temp
* pointer forward until we've read the file enough times
* to fill the buffer. NOTE: It's probably not efficient
* to bother with the overhead of streaming a file that's
* not at least as large as the buffer... */
lpTemp += uChkErr;
dwLen1 -= uChkErr;
nChkErr = WaveStartDataRead( &lpwiWave->hmmio,
&lpwiWave->mmck,
&lpwiWave->mmckInRIFF );
// added by Liu Gang, Aug 13, 1997
// to fix a bug
if( nChkErr != 0 ) break;
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen1,
lpTemp,
&lpwiWave->mmck, &uChkErr );
// added by Liu Gang, Aug 13, 1997
if( nChkErr != 0 ) break;
} while( uChkErr < dwLen1 );
}
}
}
/*
* The bDonePlaying flag is set by the caller if the user stops playback
* before the end of the WAVE file is encountered. It tells us to cut this
* racket out and play nothing in case it takes the caller a couple
* interrupts to shut off the timer.
*/
else if( dwLen1 && lpwiWave->bDonePlaying )
{
// Set the appropriate silence value
memset( lpWrite1,
lpwiWave->pwfx->wBitsPerSample == 8 ? 128 : 0,
dwLen1);
}
if( dwLen2 && !lpwiWave->bDonePlaying )
{
nChkErr = WaveReadFile( lpwiWave->hmmio, (UINT)dwLen2, lpWrite2,
&lpwiWave->mmck, &uChkErr );
if( uChkErr < (UINT)dwLen2 )
{
if( !lpwiWave->bLoopFile )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -