如何消除在DirectShow过滤器链延迟1秒? (使用Delphi和DSPACK) [英] How to eliminate 1 second delay in DirectShow filter chain? (Using Delphi and DSPACK)

查看:1139
本文介绍了如何消除在DirectShow过滤器链延迟1秒? (使用Delphi和DSPACK)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用DSPACK组件库从系统的preferred音频输入设备音频发送到Skype的一个Delphi 6 Pro的应用程序。我使用的是TSampleGrabber组件进军过滤器图表链,然后发送音频缓冲区的Skype。现在的问题是,我只得到一次音频第二。换句话说,对于TSampleGrabber实例OnBuffer()事件只触发一次用了整整一秒的价值的数据缓冲区中的参数的第二。我需要知道如何修改我的过滤器图链所以它从输入设备以较快的区间数据抓取不止一次第二。如果可能的话,我想以最快的速度做到这一点,因为每个50毫秒或​​至少每100ms。

我的f​​ilter图表链包括了在顶部映射到系统的preferred音频输入设备的TFilter的。我附上滤波器的输出引脚为'WAV目的地分配TFilter的输入引脚,所以我可以得到PCM WAV格式的样本。我再附上了WAV目的地滤波器的输出引脚连接到TSampleGrabber实例的输入引脚。什么我需要改变,以获得TSampleGrabber OnBuffer()事件触发以更快的间隔?


更新:基于罗马的r回答我能够实现,我下面展示的解决方案。一个音符。他的链接带领我到下面的博客文章,这是有帮助的解决方案:

http://sid6581.word$p$pss.com/2006/10/09/minimizing-audio-capture-latency-in-directshow/

  //变量声明为输出引脚来操纵。
VAR
    intfCapturePin:宜宾;...............
    //将这个code你已经初始化您的音频捕获设备后
    // TFilter例如*和*设置它的波形音频格式。我的变量
    //这是FFiltAudCap。我相信你需要之前设置缓冲区的大小
    //连接了过滤器的引脚。媒体类型是
    //前面(theMediaType)检索时我初始化音频
    //输入设备过滤器,所以你需要做类似。    //取得对音频俘获装置,以期望的输出引脚的参考。
    与FFiltAudCap为IBaseFilter做
        CheckDSError(findPin(StringToOleStr('捕获'),intfCapturePin));    如果未分配(intfCapturePin),然后
        提高Exception.Create(无法找到音频输入设备的捕捉输出引脚');    //设置捕获设备缓冲区为50 ms值得音频数据的
    //减少延迟。注:如果设备没有这将失败
    //支持你的愿望,以便确保您注意的等待时间。
    setBufferLatency(intfCapturePin为IAMBufferNegotiation,50,theMediaType);..................//该setBufferLatency()过程。
程序setBufferLatency(
                //一个缓冲协商接口指针。
                intfBufNegotiate:IAMBufferNegotiation;
                //以毫秒为单位所需的延迟。
                bufLatencyMS:WORD;
                //媒体类型的音频流设置为。
                theMediaType:TMediaType);
VAR
    allocProp:_AllocatorProperties;
    wfex:TWaveFor​​matEx;
开始
    如果未分配(intfBufNegotiate),然后
        提高Exception.Create('缓冲区谈判接口对象是未分配的。');    //使用波计算每秒的字节数
    //属于给定介质类型的格式。
    wfex:= getWaveFor​​mat(theMediaType);    如果wfex.nAvgBytesPerSec = 0则
        提高Exception.Create(每秒值的平均字节给定的介质类型为0');    allocProp.cbAlign:= -1; // -1表示没有preference。
    //计算所需要的缓冲区的大小,以获得所需
    //在毫秒延迟给定的每秒平均字节
    //媒体类型的音频格式。
    allocProp.cbBuffer:= TRUNC(wfex.nAvgBytesPerSec *(bufLatencyMS / 1000));
    allocProp.cb preFIX:= -1;
    allocProp.cBuffers:= -1;    //尝试将缓冲区的大小设置为所需。
    CheckDSError(intfBufNegotiate.SuggestAllocatorProperties(allocProp));
结束;


解决方案

我想你需要微调音频捕获过滤器在你想要的大小,即足够短,使整体延时小的缓冲区来捕捉。

音频采集器暴露 IAMBufferNegotiation 输出引脚接口和 SuggestAllocatorProperties 允许您指定缓冲区的配置。

详情参见:<一href=\"http://social.msdn.microsoft.com/Forums/en-US/windowsdirectshowdevelopment/thread/9257bab3-383a-4e8c-8da6-7d9548f09716/\">Configuring Windows Media音频连接codeR DMO减少延迟。

I have a Delphi 6 Pro app that uses the DSPACK component library to send audio to Skype from the system's preferred audio input device. I am using a TSampleGrabber component to tap into the Filter Graph chain and then send the audio buffers to Skype. The problem is that I am only getting audio once a second. In other words, the OnBuffer() event for the TSampleGrabber instance only fires once a second with a full second's worth of data in the Buffer parameter. I need to know how to modify my Filter Graph chain so it grabs data from the input device at a faster interval than once a second. If possible, I'd like to do it as fast as every 50 ms or at least every 100ms.

My Filter Graph chain consists of a TFilter that is mapped to the system's preferred audio input device at the top. I attach the output pins of that filter to the input pins of a 'WAV Dest' assigned TFilter so I can get the samples in PCM WAV format. I then attach the output pins of the 'WAV Dest' filter to the input pins of the TSampleGrabber instance. What do I need to change to get the TSampleGrabber OnBuffer() event to fire at a faster interval?


UPDATE: Based on Roman R's answer I was able to implement a solution that I am showing below. One note. His link led me to the following blog post that was helpful in solution:

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;

解决方案

I suppose you need to fine tune Audio Capture filter to capture in buffers of the size you want, i.e. short enough to make overall latency small.

Audio capture filters expose IAMBufferNegotiation interface on output pins and SuggestAllocatorProperties lets you specify buffer configuration.

See for more info: Configuring Windows Media Audio Encoder DMO to reduce delay.

这篇关于如何消除在DirectShow过滤器链延迟1秒? (使用Delphi和DSPACK)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆