我有一个用C编写的DirectSound应用程序,运行在Windows 7上。该应用程序仅捕获一些声音帧,然后播放它们。为了检查捕获结果的完整性,我将PCM数据写到一个文件中,可以使用aplay在Linux中播放该文件。

不幸的是,声音断断续续,有时会产生结结(在Linux中以错误的速度播放)。奇怪的是,如果在捕获时未在回放缓冲区中播放PCM数据,则在播放捕获文件时观察到的失真量会减少。

这是我的WAVEFORMATEX的初始化:

memset(&wfx, 0, sizeof(WAVEFORMATEX));
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 1;
wfx.nSamplesPerSec = sampleRate;
wfx.wBitsPerSample = sampleBitWidth;
wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign code here

sampleRate为8000,sampleBitWidth为16。

我使用相同的结构创建捕获和播放缓冲区,并且捕获缓冲区具有3个通知位置。我开始捕捉:
lpDsCaptureBuffer->Start(DSCBSTART_LOOPING);

然后,我触发一个回放线程,该线程在与通知点关联的事件上调用WaitForMultipleObjects。收到通知后,我将重置所有事件,并将1个或2个捕获缓冲区复制到本地缓冲区,然后将其传递给播放例程:
void playFromBuff(LPVOID captureBuff,DWORD captureLen) {
  LPVOID playBuff;
  DWORD playLen;
  HRESULT hr;

  hr = lpDsPlaybackBuffer->Lock(0L,captureLen,&playBuff,&playLen,NULL,0L,0L);

  memcpy(playBuff,captureBuff,playLen);
  hr = lpDsPlaybackBuffer->Unlock(playBuff,playLen,NULL,0L);
  hr = lpDsPlaybackBuffer->SetCurrentPosition(0L);
  hr = lpDsPlaybackBuffer->Play(0L,0L,0L);
}

(省略了一些错误检查)。

请注意,播放缓冲区没有通知位置。每次从捕获缓冲区中获取一个块时,都会锁定从位置0开始的回放缓冲区。

由WaitForMultipleObjects保护的捕获代码如下所示:
    lpDsCaptureBuffer->GetCurrentPosition(NULL,&readPos);

    hr = lpDsCaptureBuffer->Lock(...,...,&captureBuff1,&captureLen1,&captureBuff2,&captureLen2,0L);

省略号包含涉及当前和以前看到的读取位置的计算。我忽略了那些可能错误的计算-我怀疑这就是问题所在。

我的通知位置是1024的倍数。但是报告的读取位置是1500、2500和3500。因此,如果我看到一个1500的读取位置,那是否意味着我可以从字节0到1500进行读取。下一次看到2500时,这是否意味着我应该从1501读到2500?为什么这些读取位置与我的通知位置不完全对应?这里正确的算法是什么?

我尝试了一种更简单的选择,即在捕获缓冲区已满时停止捕获,而没有其他通知位置。但是我认为,这意味着允许某些声音逃脱捕获。

最佳答案



如今,DirectSound API已成为其他“真实”音频捕获API之上的兼容性层。这意味着内部音频捕获将填充一些缓冲区(尤其是500的倍数),然后将填充的缓冲区传递给DirectSound捕获,DirectSound捕获又将其报告给您。这就解释了为什么您看到读取位置是500的倍数的原因,因为DirectSound本身具有以这种方式可用的数据。

由于您对获取捕获的数据感兴趣,因此您的假设是正确的,即您主要对读取位置感兴趣。您会收到通知,并且知道可以安全读取哪些偏移量。由于捕获API是分层的,因此涉及一些延迟,因为各层需要先在彼此之间传递数据块,然后才能使它们可用。

关于windows - 如何避免DirectSound中的失真和卡顿?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28039351/

10-11 16:55