Как устранить задержку в 1 секунду в цепочке фильтров DirectShow? (С использованием Delphi и DSPACK)
У меня есть приложение Delphi 6 Pro, которое использует библиотеку компонентов DSPACK для отправки аудио в Skype с предпочтительного устройства ввода звука системы. Я использую компонент TSampleGrabber, чтобы подключиться к цепочке фильтров и затем отправить аудио буферы в Skype. Проблема в том, что я получаю аудио только раз в секунду. Другими словами, событие OnBuffer() для экземпляра TSampleGrabber вызывается только один раз в секунду с полными секундами данных в параметре Buffer. Мне нужно знать, как изменить мою цепочку графиков фильтров, чтобы она собирала данные с устройства ввода с более быстрым интервалом, чем раз в секунду. Если возможно, я бы хотел сделать это так быстро, как каждые 50 мс или как минимум каждые 100 мс.
Цепочка "Мой график фильтра" состоит из фильтра TFilter, который привязан к предпочтительному устройству ввода аудио в верхней части. Я прикрепляю выходные выводы этого фильтра к входным контактам назначенного "WAV Dest" TFilter, чтобы я мог получить сэмплы в формате 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 ответ
Я полагаю, вам необходимо настроить фильтр Audio Capture для захвата в буферы нужного размера, то есть достаточно коротких, чтобы уменьшить общую задержку.
Фильтры захвата звука выставляют IAMBufferNegotiation
интерфейс на выходных контактах и SuggestAllocatorProperties
позволяет указать конфигурацию буфера.
См. Для получения дополнительной информации: Настройка Windows Media Audio Encoder DMO для уменьшения задержки.