C ++ - DirectSoundBuffer停止在特定位置播放 - 没有通知

时间:2013-05-10 04:11:52

标签: c++ streaming directx directsound

我正在使用DirectSound的DirectSoundBuffer播放我通过网络传输的语音数据。语音/语音的本质是它不一定经常流(它开始和停止),它也可能有不同的数据包大小(这使得很难预测缓冲区应该停止的位置)。我保留了一个StoppingPoint变量,用于跟踪我写入缓冲区的位置(它还考虑了此缓冲区的循环特性)。如果达到StoppingPoint,我想停止播放我的缓冲区。此外,我StoppingPoint也意味着我也想开始写作。

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

另外,我无法使用通知,因为为了使用通知,必须停止缓冲区。但就我而言,当缓冲区正在播放时,很可能会有更多数据进入,从而推迟我的'StoppingPoint`值。

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

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

注意:我没有包含任何代码,因为这更像是我需要的高级解决方案。我的实施是非常直接的,典型的,并且大多数情况下它的工作。我只需要朝正确的方向轻推即可消除StoppingPoint的过冲。也许有一个我可以使用的功能?还是通常用于实现此目的的其他一些算法?

1 个答案:

答案 0 :(得分:0)

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

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

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

同样,如果我在这里做了任何明显的恶事,请告诉我!