【问题标题】:C++ - DirectSoundBuffer stop playing at specific location - no notificationsC++ - DirectSoundBuffer 停止在特定位置播放 - 没有通知
【发布时间】:2013-05-04 17:07:09
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: c++ streaming directx directsound


    【解决方案1】:

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

    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
    

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

    【讨论】:

      猜你喜欢
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多