📄 captureecho.cpp
字号:
CheckHRESULT(hr, "IDirectSoundNotify::SetNotificationPositions", return);
hr = piDSCB->Start(DSCBSTART_LOOPING);
CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Start(DSCBSTART_LOOPING)", return);
dwStartTime = GetTickCount();
dwTimeElapsed = 0;
dwLastReadPosition = 0;
dwWritePosition = 0;
fPlaying = false;
while (m_dwTimeout>dwTimeElapsed && dwWaitResult != WAIT_TIMEOUT)
{
dwWaitResult = WaitForMultipleObjects(nNumStreamingBlocks, (const HANDLE*) rhEvents, FALSE, 2 * m_dwDelay);
//dbgout(TEXT("wait returns %d\n"), dwWaitResult);
do
{
// Wait until portion of the capture buffer we want to lock is available.
// If notifications are sent correctly this loop will execute only once.
hr = piDSCB->GetCurrentPosition(&dwTmp, &dwReadPosition);
CheckHRESULT(hr, "IDirectSoundCapture::GetCurrentPosition", return);
// adjust the read position if we're wrapped around the end of the buffer
if (dwReadPosition<dwLastReadPosition)
dwReadPosition+=dwBufferSize;
} while (dwLastReadPosition+dwBlockSize > dwReadPosition);
// Note: Some types of audio systems use different clocks for capture and playback,
// which can cause the streaming rate from the capture buffer to be slightly
// different than the streaming rate into the playback buffer. If that is the case,
// there will eventually be a locking conflict when we try to lock the playback buffer.
// This test will stop the audio capture if this condition occurs.
// If this condition happens on your HW, it will happen sooner with small block sizes.
// Using the -t and -d options, you can determine how large a block is needed to
// achieve a reasonable mean time before failure.
# ifdef DEBUG
if (fPlaying)
{
// Get the play position
DWORD dwCurrentPlayPosition, dwCurrentWritePosition;
hr = piDSB->GetCurrentPosition(&dwCurrentPlayPosition, &dwCurrentWritePosition);
CheckHRESULT(hr, "IDirectSoundBuffer::GetCurrentPosition", return);
if (dwCurrentWritePosition<dwCurrentPlayPosition)
dwCurrentWritePosition += dwBufferSize;
if ((dwCurrentPlayPosition>=dwWritePosition && dwCurrentPlayPosition<=dwWritePosition+dwBlockSize)
|| (dwCurrentWritePosition>=dwWritePosition && dwCurrentWritePosition<=dwWritePosition+dwBlockSize))
{
dbgout(TEXT("IDirectSoundBuffer::Lock collided with the play position of the playback buffer at time %lums.\n"), GetTickCount()-dwStartTime);
break;
}
}
# endif
//
// Make sure that the write cursor is on a DWORD BOUNDARY.
// This prevents copying audio data from an even address to an
// odd address, or vice versa, which can lead to static or
// white noise in the final audio.
//
// Without this fix, the application can sometimes copy 16-bit data
// from an odd address to an even address, which has the effect of
// swapping the high and low bytes of 16-bit PCM samples.
//
dwWritePosition &= (DWORD) ~3;
// Lock the first half of the capture buffer and the next block in the playback buffer
hr = piDSCB->Lock(dwLastReadPosition, dwBlockSize,
reinterpret_cast<LPVOID*>(&pbAudioCapturePtr0), &dwAudioCaptureBytes0,
reinterpret_cast<LPVOID*>(&pbAudioCapturePtr1), &dwAudioCaptureBytes1,
0);
CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Lock", return);
// Lock the next block of the playback buffer
hr = piDSB->Lock(dwWritePosition, dwBlockSize,
(LPVOID*)&pbAudioPlaybackPtr0, &dwAudioPlaybackBytes0,
(LPVOID*)&pbAudioPlaybackPtr1, &dwAudioPlaybackBytes1,
0);
CheckHRESULT(hr, "IDirectSoundBuffer::Lock", return);
// Sanity check
ASSERT(dwAudioCaptureBytes0+dwAudioCaptureBytes1==dwBlockSize);
ASSERT(dwAudioPlaybackBytes0+dwAudioPlaybackBytes1==dwBlockSize);
// Copy the capture data to the locked portion of the playback buffer
if (dwAudioPlaybackBytes0 <= dwAudioCaptureBytes0)
{
dwTmp = dwAudioCaptureBytes0-dwAudioPlaybackBytes0;
memcpy(pbAudioPlaybackPtr0, pbAudioCapturePtr0, dwAudioPlaybackBytes0);
if (dwTmp>0)
{
memcpy(pbAudioPlaybackPtr1, pbAudioCapturePtr0 + dwAudioPlaybackBytes0, dwTmp);
if (dwAudioCaptureBytes1)
memcpy(pbAudioPlaybackPtr1+dwTmp, pbAudioCapturePtr1, dwAudioCaptureBytes1);
}
}
else
{
memcpy(pbAudioPlaybackPtr0, pbAudioCapturePtr0, dwAudioCaptureBytes0);
dwTmp = dwAudioPlaybackBytes0-dwAudioCaptureBytes0;
if (dwTmp>0)
{
memcpy(pbAudioPlaybackPtr0+dwAudioCaptureBytes0, pbAudioCapturePtr1, dwTmp);
if (dwAudioCaptureBytes1>dwTmp)
memcpy(pbAudioPlaybackPtr1, pbAudioCapturePtr1+dwTmp, dwAudioCaptureBytes1-dwTmp);
}
}
// Unlock the buffers
hr = piDSB->Unlock((LPVOID*)pbAudioPlaybackPtr0, dwAudioPlaybackBytes0,
(LPVOID*)pbAudioPlaybackPtr1, dwAudioPlaybackBytes1);
CheckHRESULT(hr, "IDirectSoundBuffer::Unlock", return);
hr = piDSCB->Unlock((LPVOID*)pbAudioCapturePtr0, dwAudioCaptureBytes0,
(LPVOID*)pbAudioCapturePtr1, dwAudioCaptureBytes1);
CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Unlock", return);
if (!fPlaying && dwWritePosition != 0)
{
hr = piDSB->Play(0,0,DSBPLAY_LOOPING);
CheckHRESULT(hr, "IDirectSoundBuffer::Play", return);
fPlaying=true;
}
dwLastReadPosition = (dwLastReadPosition+dwBlockSize)%dwBufferSize;
dwWritePosition = (dwWritePosition+dwBlockSize)%dwBufferSize;
dwTimeElapsed = GetTickCount()-dwStartTime;
}
// clear the next playback block to prevent playing noise when we reach the end
// of the last block
hr = piDSB->Lock(dwWritePosition, dwBlockSize,
(LPVOID*)&pbAudioPlaybackPtr0, &dwAudioPlaybackBytes0,
(LPVOID*)&pbAudioPlaybackPtr1, &dwAudioPlaybackBytes1,
0);
CheckHRESULT(hr, "IDirectSoundBuffer::Lock", return);
memset(pbAudioPlaybackPtr0, 0, dwAudioPlaybackBytes0);
if (pbAudioPlaybackPtr1)
memset(pbAudioPlaybackPtr1, 0, dwAudioPlaybackBytes1);
hr = piDSB->Unlock((LPVOID*)pbAudioPlaybackPtr0, dwAudioPlaybackBytes0,
(LPVOID*)pbAudioPlaybackPtr1, dwAudioPlaybackBytes1);
CheckHRESULT(hr, "IDirectSoundBuffer::Unlock", return);
// Wait until the next notification is sent. We're no longer streaming, but we're
// going to continue to run the capture buffer to use its notification
dwTmp = ((dwWritePosition/dwBlockSize)+nNumStreamingBlocks+1)%nNumStreamingBlocks;
dwWaitResult = WaitForMultipleObjects(1, (const HANDLE*) &rhEvents[dwTmp], FALSE, m_dwDelay);
hr = piDSB->Stop();
CheckHRESULT(hr, "IDirectSoundBuffer::Stop", return);
hr = piDSCB->Stop();
CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Stop", return);
dbgout(TEXT("Capturing completed.\n"));
}
void CCaptureEchoApplication::DisplayUsage()
{
dbgout(TEXT("\nCaptureEcho Usage:\n\tCaptureEcho [-f format] [-d delay] [-t timeout]\n"));
dbgout(TEXT("\t-f capture format index (0-11) (See readme.txt)\n"));
dbgout(TEXT("\t-d approximate delay in milliseconds, default = %lu\n"), DEFAULT_DELAY);
dbgout(TEXT("\t NOTE: Delay must be at least 500ms.\n"));
dbgout(TEXT("\t-t timeout in seconds, default = %lu\n"), DEFAULT_TIMEOUT/1000);
dbgout(TEXT("\t NOTE: Timeout must be greater than 4 times the delay.\n"));
dbgout(TEXT("\t It will also be converted to ms and quantized to the delay.\n"));
}
bool CCaptureEchoApplication::ProcessCommandLine()
{
LPCTSTR pszHelpOption = _tcsstr(m_pszCommandLine, TEXT("-?"));
if (pszHelpOption==NULL) LPCTSTR pszHelpOption = _tcsstr(m_pszCommandLine, TEXT("-h"));
LPCTSTR pszTimeOption = _tcsstr(m_pszCommandLine, TEXT("-t"));
LPCTSTR pszDelayOption = _tcsstr(m_pszCommandLine, TEXT("-d"));
LPCTSTR pszFormatOption = _tcsstr(m_pszCommandLine, TEXT("-f"));
if (pszHelpOption!=NULL)
{
DisplayUsage();
return false;
}
if (pszDelayOption!=NULL)
{
pszDelayOption+=2;
// Skip Whitespace
while (_istspace(*pszDelayOption))
pszDelayOption++;
m_dwDelay = _ttoi(pszDelayOption);
if (m_dwDelay<500)
{
DisplayUsage();
return false;
}
}
if (pszTimeOption!=NULL)
{
pszTimeOption+=2;
// Skip Whitespace
while (_istspace(*pszTimeOption))
pszTimeOption++;
m_dwTimeout = _ttoi(pszTimeOption) * 1000;
if (m_dwTimeout==0)
{
DisplayUsage();
return false;
}
if (m_dwTimeout<4*m_dwDelay)
{
dbgout(TEXT("ERROR: Timeout must be at least 4 times the delay.\n"));
DisplayUsage();
return false;
}
m_dwTimeout -= m_dwTimeout%m_dwDelay;
}
if (pszFormatOption!=NULL)
{
pszFormatOption+=2;
// Skip Whitespace
while (_istspace(*pszFormatOption))
pszFormatOption++;
m_dwFormatIndex = _ttoi(pszFormatOption);
if (m_dwFormatIndex > NUM_SUPPORTED_CAPTURE_FORMATS ||
m_dwFormatIndex < 0)
{
DisplayUsage();
return false;
}
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -