2

我正在使用 DirectSound 的 DirectSoundBuffer 播放通过网络传输的语音数据。语音/语音的本质是它不一定不断地流式传输(它开始和停止),它也可以以不同的数据包大小出现(这使得很难预测缓冲区应该停止的位置)。我保留一个StoppingPoint变量来跟踪我在缓冲区中写入的位置(它还考虑了该缓冲区的循环性质)。如果StoppingPoint达到,我想停止播放我的缓冲区。另外,我StoppingPoint还要指出我也想从哪里开始写作。

My buffer
|==============================|--------------------------|
      ^                        ^             ^
      |                        |             |
  Voice Data            Stopping point   Old/Garbage
                                            data

另外,我不能使用通知,因为为了使用通知,必须停止缓冲区。但就我而言,当缓冲区播放时,很可能会有更多数据进入,从而推回我的“StoppingPoint”值。

我现在拥有的是一个每帧都调用的函数。除其他外,此功能正在检查播放光标的位置。如果播放光标经过该StoppingPoint位置,它会停止缓冲区,并将播放光标移回该StoppingPoint位置。到目前为止,这似乎工作正常,但正如您所料,Play 光标经常超过StoppingPoint. 这意味着每次到达流数据的末尾时都会播放一些旧/垃圾数据。

我只是好奇是否有办法在特定偏移处停止播放 DirectSoundBuffer?我想要的是将数据写入缓冲区,然后播放,然后让它精确地停在我的StoppingPoint变量描述的位置而不会超出它。

注意:我没有包含任何代码,因为这更像是我需要的高级解决方案。我的实现非常简单、典型,并且在大多数情况下它确实有效。我只需要朝正确的方向轻推即可消除我的StoppingPoint. 也许有一个我可以使用的功能?或者其他一些常用来实现这一点的算法?

4

1 回答 1

0

我想出了一个解决方案,但我仍然对任何反馈或替代解决方案感兴趣。我不确定我这样做的方式是否可行,但它似乎正在产生预期的结果。虽然,我的解决方案感觉有点太复杂了......

1)每当我写数据时,我现在都写在缓冲区Write CursorStoppingPoint- 以较晚者为准。这是为了避免停止,然后在 Play Cursor 和 Write Cursor 之间的“不可触及”空间中写入,其数据已经专用于播放。

DWORD writeCursorOffset = 0;
buffer->GetCurrentPosition(NULL, &writeCursorOffset); 

//if write cursor has passed stopping point, then we need to write from there. 
//So update m_StoppingPoint to reflect the new writing position.
m_StoppingPoint = m_StoppingPoint > writeCursorOffset ? m_StoppingPoint : writeCursorOffset;

2)我在每次写入后添加了一些静音,但我留下StoppingPoint了指向实际语音数据的末尾。例如。

|==============================|*********|---------------------|
     ^                         ^      ^              ^
     |                         |      |              |
Voice data                  Stopping  Silence    Old/Garbage
                             Point                  Data

3)如果缓冲区Play Cursor通过了StoppingPoint,我会停止播放缓冲区。即使播放光标在这里过冲,它所播放的只是静音。

//error checking removed for demonstration purposes
buffer->Stop();

4)停止后我会立即更新StoppingPoint为等于沉默的结束。这将确保当更多语音数据进入时,缓冲区不会首先播放任何静音。

//don't forget that modulo at the end - circular buffer!
m_StoppingPoint = (m_StoppingPoint + SILENCE_BUFFER_SIZE) % BufferSize;

|==============================|*********|-------------------|
                                         ^ 
                                         | 
                                    Move Stopping
                                      Point here

再说一次,如果我在这里做了什么明显的坏事,请告诉我!

于 2013-05-10T06:35:48.107 回答