【问题标题】:How to eliminate 1 second delay in DirectShow filter chain? (Using Delphi and DSPACK)如何消除 DirectShow 过滤器链中的 1 秒延迟? (使用 Delphi 和 DSPACK)
【发布时间】:2011-10-24 20:15:42
【问题描述】:

我有一个 Delphi 6 Pro 应用程序,它使用 DSPACK 组件库从系统的首选音频输入设备向 Skype 发送音频。我正在使用 TSampleGrabber 组件来接入过滤器图链,然后将音频缓冲区发送到 Skype。问题是我每秒只能获得一次音频。换句话说,TSampleGrabber 实例的 OnBuffer() 事件每秒仅触发一次,Buffer 参数中包含一整秒的数据。我需要知道如何修改我的过滤器图链,以便它以比每秒一次更快的间隔从输入设备获取数据。如果可能的话,我希望每 50 毫秒或至少每 100 毫秒尽快完成一次。

我的过滤器图链由一个 TFilter 组成,它映射到顶部的系统首选音频输入设备。我将该滤波器的输出引脚连接到分配了“WAV Dest”的 TFilter 的输入引脚,这样我就可以获得 PCM WAV 格式的样本。然后,我将“WAV Dest”过滤器的输出引脚连接到 TSampleGrabber 实例的输入引脚。我需要进行哪些更改才能让 TSampleGrabber OnBuffer() 事件以更快的间隔触发?


更新:根据 Roman R 的回答,我能够实施我在下面展示的解决方案。一注。他的链接将我带到以下对解决方案有帮助的博客文章:

http://sid6581.wordpress.com/2006/10/09/minimizing-audio-capture-latency-in-directshow/

// Variable declaration for output pin to manipulate.
var
    intfCapturePin: IPin;

...............


    // Put this code after you have initialized your audio capture device
    //  TFilter instance *and* set it's wave audio format.  My variable for
    //  this is FFiltAudCap.  I believe you need to set the buffer size before
    //  connecting up the pins of the Filters.  The media type was
    //  retrieved earlier (theMediaType) when I initialized the audio
    //  input device Filter so you will need to do similarly.

    // Get a reference to the desired output pin for the audio capture device.
    with FFiltAudCap as IBaseFilter do
        CheckDSError(findPin(StringToOleStr('Capture'), intfCapturePin));

    if not Assigned(intfCapturePin) then
        raise Exception.Create('Unable to find the audio input device''s Capture output pin.');

    // Set the capture device buffer to 50 ms worth of audio data to
    //  reduce latency.  NOTE: This will fail if the device does not
    //  support the latency you desire so make sure you watch out for that.
    setBufferLatency(intfCapturePin as IAMBufferNegotiation, 50, theMediaType);

..................

// The setBufferLatency() procedure.
procedure setBufferLatency(
                // A buffer negotiation interface pointer.
                intfBufNegotiate: IAMBufferNegotiation;
                // The desired latency in milliseconds.
                bufLatencyMS: WORD;
                // The media type the audio stream is set to.
                theMediaType: TMediaType);
var
    allocProp: _AllocatorProperties;
    wfex: TWaveFormatEx;
begin
    if not Assigned(intfBufNegotiate) then
        raise Exception.Create('The buffer negotiation interface object is unassigned.');

    // Calculate the number of bytes per second using the wave
    // format belonging to the given Media Type.
    wfex := getWaveFormat(theMediaType);

    if wfex.nAvgBytesPerSec = 0 then
        raise Exception.Create('The average bytes per second value for the given Media Type is 0.');

    allocProp.cbAlign := -1;  // -1 means "no preference".
    // Calculate the size of the buffer needed to get the desired
    //  latency in milliseconds given the average bytes per second
    //  of the Media Type's audio format.
    allocProp.cbBuffer := Trunc(wfex.nAvgBytesPerSec * (bufLatencyMS / 1000));
    allocProp.cbPrefix := -1;
    allocProp.cBuffers := -1;

    // Try to set the buffer size to the desired.
    CheckDSError(intfBufNegotiate.SuggestAllocatorProperties(allocProp));
end;

【问题讨论】:

    标签: delphi audio directshow dspack


    【解决方案1】:

    我想您需要微调音频捕获过滤器以在所需大小的缓冲区中捕获,即足够短以使整体延迟变小。

    音频捕获过滤器在输出引脚上公开IAMBufferNegotiation 接口,SuggestAllocatorProperties 允许您指定缓冲区配置。

    查看更多信息:Configuring Windows Media Audio Encoder DMO to reduce delay

    【讨论】:

    • 感谢@Roman R。我已经更新了我的原始帖子,以包含我在您的原始链接后找到的解决方案。
    猜你喜欢
    • 2012-04-25
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2017-01-22
    相关资源
    最近更新 更多