📄 dsound_wrapper.c
字号:
} AddTraceMessage("playCursor", playCursor); AddTraceMessage("dsw_WriteOffset", dsw->dsw_WriteOffset); // Determine size of gap between playIndex and WriteIndex that we cannot write into. playWriteGap = writeCursor - playCursor; if( playWriteGap < 0 ) playWriteGap += dsw->dsw_OutputSize; // unwrap /* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */ /* Attempt to detect playCursor wrap-around and correct it. */ if( dsw->dsw_OutputRunning && (dsw->dsw_CounterTicksPerBuffer.QuadPart != 0) ) { /* How much time has elapsed since last check. */ LARGE_INTEGER currentTime; LARGE_INTEGER elapsedTime; long bytesPlayed; long bytesExpected; long buffersWrapped; QueryPerformanceCounter( ¤tTime ); elapsedTime.QuadPart = currentTime.QuadPart - dsw->dsw_LastPlayTime.QuadPart; dsw->dsw_LastPlayTime = currentTime; /* How many bytes does DirectSound say have been played. */ bytesPlayed = playCursor - dsw->dsw_LastPlayCursor; if( bytesPlayed < 0 ) bytesPlayed += dsw->dsw_OutputSize; // unwrap dsw->dsw_LastPlayCursor = playCursor; /* Calculate how many bytes we would have expected to been played by now. */ bytesExpected = (long) ((elapsedTime.QuadPart * dsw->dsw_OutputSize) / dsw->dsw_CounterTicksPerBuffer.QuadPart); buffersWrapped = (bytesExpected - bytesPlayed) / dsw->dsw_OutputSize; if( buffersWrapped > 0 ) { AddTraceMessage("playCursor wrapped! bytesPlayed", bytesPlayed ); AddTraceMessage("playCursor wrapped! bytesExpected", bytesExpected ); playCursor += (buffersWrapped * dsw->dsw_OutputSize); bytesPlayed += (buffersWrapped * dsw->dsw_OutputSize); } /* Maintain frame output cursor. */ dsw->dsw_FramesPlayed += (bytesPlayed / dsw->dsw_BytesPerFrame); } numBytesEmpty = playCursor - dsw->dsw_WriteOffset; if( numBytesEmpty < 0 ) numBytesEmpty += dsw->dsw_OutputSize; // unwrap offset /* Have we underflowed? */ if( numBytesEmpty > (dsw->dsw_OutputSize - playWriteGap) ) { if( dsw->dsw_OutputRunning ) { dsw->dsw_OutputUnderflows += 1; AddTraceMessage("underflow detected! numBytesEmpty", numBytesEmpty ); } dsw->dsw_WriteOffset = writeCursor; numBytesEmpty = dsw->dsw_OutputSize - playWriteGap; } *bytesEmpty = numBytesEmpty; return hr;}/************************************************************************************/HRESULT DSW_ZeroEmptySpace( DSoundWrapper *dsw ){ HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; long bytesEmpty; hr = DSW_QueryOutputSpace( dsw, &bytesEmpty ); // updates dsw_FramesPlayed if (hr != DS_OK) return hr; if( bytesEmpty == 0 ) return DS_OK; // Lock free space in the DS hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, bytesEmpty, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy the buffer into the DS ZeroMemory(lpbuf1, dwsize1); if(lpbuf2 != NULL) { ZeroMemory(lpbuf2, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize; IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); dsw->dsw_FramesWritten += bytesEmpty / dsw->dsw_BytesPerFrame; } return hr;}/************************************************************************************/HRESULT DSW_WriteBlock( DSoundWrapper *dsw, char *buf, long numBytes ){ HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; // Lock free space in the DS hr = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, dsw->dsw_WriteOffset, numBytes, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy the buffer into the DS CopyMemory(lpbuf1, buf, dwsize1); if(lpbuf2 != NULL) { CopyMemory(lpbuf2, buf+dwsize1, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_WriteOffset = (dsw->dsw_WriteOffset + dwsize1 + dwsize2) % dsw->dsw_OutputSize; IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); dsw->dsw_FramesWritten += numBytes / dsw->dsw_BytesPerFrame; } return hr;}/************************************************************************************/DWORD DSW_GetOutputStatus( DSoundWrapper *dsw ){ DWORD status; if (IDirectSoundBuffer_GetStatus( dsw->dsw_OutputBuffer, &status ) != DS_OK) return( DSERR_INVALIDPARAM ); else return( status );}#if SUPPORT_AUDIO_CAPTURE/* These routines are used to support audio input. * Do NOT compile these calls when using NT4 because it does * not support the entry points. *//************************************************************************************/HRESULT DSW_InitInputDevice( DSoundWrapper *dsw, LPGUID lpGUID ){ HRESULT hr = DirectSoundCaptureCreate( lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr != DS_OK ) return hr; return hr;}/************************************************************************************/HRESULT DSW_InitInputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bytesPerBuffer ){ DSCBUFFERDESC captureDesc; WAVEFORMATEX wfFormat; HRESULT result; // Define the buffer format wfFormat.wFormatTag = WAVE_FORMAT_PCM; wfFormat.nChannels = nChannels; wfFormat.nSamplesPerSec = nFrameRate; wfFormat.wBitsPerSample = 8 * sizeof(short); wfFormat.nBlockAlign = wfFormat.nChannels * (wfFormat.wBitsPerSample / 8); wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; wfFormat.cbSize = 0; /* No extended format info. */ dsw->dsw_InputSize = bytesPerBuffer; // ---------------------------------------------------------------------- // Setup the secondary buffer description ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC)); captureDesc.dwSize = sizeof(DSCBUFFERDESC); captureDesc.dwFlags = 0; captureDesc.dwBufferBytes = bytesPerBuffer; captureDesc.lpwfxFormat = &wfFormat; // Create the capture buffer if ((result = IDirectSoundCapture_CreateCaptureBuffer( dsw->dsw_pDirectSoundCapture, &captureDesc, &dsw->dsw_InputBuffer, NULL)) != DS_OK) return result; dsw->dsw_ReadOffset = 0; // reset last read position to start of buffer return DS_OK;}/************************************************************************************/HRESULT DSW_StartInput( DSoundWrapper *dsw ){ // Start the buffer playback if( dsw->dsw_InputBuffer != NULL ) { return IDirectSoundCaptureBuffer_Start( dsw->dsw_InputBuffer, DSCBSTART_LOOPING ); } else return 0;}/************************************************************************************/HRESULT DSW_StopInput( DSoundWrapper *dsw ){ // Stop the buffer playback if( dsw->dsw_InputBuffer != NULL ) { return IDirectSoundCaptureBuffer_Stop( dsw->dsw_InputBuffer ); } else return 0;}/************************************************************************************/HRESULT DSW_QueryInputFilled( DSoundWrapper *dsw, long *bytesFilled ){ HRESULT hr; DWORD capturePos; DWORD readPos; long filled; // Query to see how much data is in buffer. // We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly // so let's pass a pointer just to be safe. hr = IDirectSoundCaptureBuffer_GetCurrentPosition( dsw->dsw_InputBuffer, &capturePos, &readPos ); if( hr != DS_OK ) { return hr; } filled = readPos - dsw->dsw_ReadOffset; if( filled < 0 ) filled += dsw->dsw_InputSize; // unwrap offset *bytesFilled = filled; return hr;}/************************************************************************************/HRESULT DSW_ReadBlock( DSoundWrapper *dsw, char *buf, long numBytes ){ HRESULT hr; LPBYTE lpbuf1 = NULL; LPBYTE lpbuf2 = NULL; DWORD dwsize1 = 0; DWORD dwsize2 = 0; // Lock free space in the DS hr = IDirectSoundCaptureBuffer_Lock ( dsw->dsw_InputBuffer, dsw->dsw_ReadOffset, numBytes, (void **) &lpbuf1, &dwsize1, (void **) &lpbuf2, &dwsize2, 0); if (hr == DS_OK) { // Copy from DS to the buffer CopyMemory( buf, lpbuf1, dwsize1); if(lpbuf2 != NULL) { CopyMemory( buf+dwsize1, lpbuf2, dwsize2); } // Update our buffer offset and unlock sound buffer dsw->dsw_ReadOffset = (dsw->dsw_ReadOffset + dwsize1 + dwsize2) % dsw->dsw_InputSize; IDirectSoundCaptureBuffer_Unlock ( dsw->dsw_InputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); } return hr;}#endif /* SUPPORT_AUDIO_CAPTURE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -