Как устранить задержку в 1 секунду в цепочке фильтров DirectShow?(С использованием Delphi и DSPACK) - PullRequest
5 голосов
/ 25 октября 2011

У меня есть приложение Delphi 6 Pro, которое использует библиотеку компонентов DSPACK для отправки звука в Skype с предпочтительного устройства ввода звука в системе. Я использую компонент TSampleGrabber, чтобы подключиться к цепочке фильтров и затем отправить аудио буферы в Skype. Проблема в том, что я получаю аудио только раз в секунду. Другими словами, событие OnBuffer () для экземпляра TSampleGrabber вызывается только один раз в секунду с полными секундами данных в параметре Buffer. Мне нужно знать, как изменить мою цепочку графиков фильтров, чтобы она собирала данные с устройства ввода с более быстрым интервалом, чем раз в секунду. Если возможно, я бы хотел сделать это так быстро, как каждые 50 мс или как минимум каждые 100 мс.

Цепочка «Мой график фильтра» состоит из фильтра TFilter, который сопоставлен с предпочтительным устройством ввода звука системы в верхней части. Я прикрепляю выходные выводы этого фильтра к входным контактам назначенного TFilter 'WAV Dest', чтобы я мог получить сэмплы в формате PCM WAV. Затем я присоединяю выходные контакты фильтра 'WAV Dest' к входным контактам экземпляра TSampleGrabber. Что мне нужно изменить, чтобы событие TSampleGrabber OnBuffer () сработало с более быстрым интервалом?


ОБНОВЛЕНИЕ : Основываясь на ответе Романа Р, я смог реализовать решение, которое я показываю ниже. Одна запись. Его ссылка привела меня к следующему сообщению в блоге, которое было полезно в решении:

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;

1 Ответ

6 голосов
/ 25 октября 2011

Полагаю, вам необходимо настроить фильтр Audio Capture для захвата в буферы нужного вам размера, то есть достаточно короткого, чтобы уменьшить общую задержку.

Фильтры захвата звука предоставляют интерфейс IAMBufferNegotiation на выходных выводах иSuggestAllocatorProperties позволяет указать конфигурацию буфера.

Подробнее см .: Настройка DMO аудиокодера Windows Media для уменьшения задержки .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...