2011-10-24 29 views
5

Tôi có một ứng dụng Delphi 6 Pro sử dụng thư viện thành phần DSPACK để gửi âm thanh đến Skype từ thiết bị đầu vào âm thanh ưa thích của hệ thống. Tôi đang sử dụng một thành phần TSampleGrabber để khai thác vào chuỗi Filter Graph và sau đó gửi các bộ đệm âm thanh đến Skype. Vấn đề là tôi chỉ nhận được âm thanh mỗi giây một lần. Nói cách khác, sự kiện OnBuffer() cho cá thể TSampleGrabber chỉ kích hoạt mỗi giây một lần với giá trị đầy đủ của dữ liệu thứ hai trong tham số Bộ đệm. Tôi cần phải biết làm thế nào để sửa đổi chuỗi Graph Filter của tôi để nó lấy dữ liệu từ thiết bị đầu vào tại một khoảng thời gian nhanh hơn một lần một giây. Nếu có thể, tôi muốn thực hiện nhanh như mọi 50 ms hoặc ít nhất 100ms một lần.Làm thế nào để loại bỏ độ trễ 1 giây trong chuỗi bộ lọc DirectShow? (Sử dụng Delphi và DSPACK)

Chuỗi biểu đồ bộ lọc của tôi bao gồm một TFilter được ánh xạ tới thiết bị đầu vào âm thanh ưa thích của hệ thống ở trên cùng. Tôi đính kèm các chân đầu ra của bộ lọc đó vào các chân đầu vào của một 'WAV Dest' đã gán TFilter để tôi có thể lấy mẫu ở định dạng PCM WAV. Sau đó tôi gắn các chốt đầu ra của bộ lọc 'WAV Dest' vào các chân đầu vào của cá thể TSampleGrabber. Tôi cần phải thay đổi gì để có được sự kiện TSampleGrabber OnBuffer() để kích hoạt trong một khoảng thời gian nhanh hơn?


CẬP NHẬT: Dựa trên câu trả lời Roman R của tôi đã có thể thực hiện một giải pháp mà tôi đang thể hiện dưới đây. Một lưu ý. liên kết của ông đã dẫn tôi đến bài viết trên blog sau đó là hữu ích trong việc giải pháp:

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; 

Trả lời

6

Tôi cho rằng bạn cần để tinh chỉnh âm thanh Capture bộ lọc để chụp trong bộ đệm của kích thước bạn muốn, tức là ngắn đủ để làm cho độ trễ tổng thể nhỏ.

Bộ lọc chụp âm thanh vạch ra giao diện IAMBufferNegotiation trên chân đầu ra và SuggestAllocatorProperties cho phép bạn chỉ định cấu hình bộ đệm.

Xem thêm thông tin: Configuring Windows Media Audio Encoder DMO to reduce delay.

+0

Cảm ơn @Roman R. Tôi đã cập nhật bài đăng gốc của mình để bao gồm giải pháp mà tôi tìm thấy sau liên kết ban đầu của bạn. –