2011-10-24 12 views
5

Ho un'app Delphi 6 Pro che utilizza la libreria dei componenti DSPACK per inviare l'audio a Skype dal dispositivo di input audio preferito del sistema. Sto utilizzando un componente TSampleGrabber per accedere alla catena del filtro grafico e quindi inviare i buffer audio a Skype. Il problema è che ricevo l'audio solo una volta al secondo. In altre parole, l'evento OnBuffer() per l'istanza TSampleGrabber si attiva solo una volta al secondo con un valore di secondo completo nel parametro Buffer. Devo sapere come modificare la mia catena del filtro grafico in modo che raccolga i dati dal dispositivo di input ad un intervallo più veloce di una volta al secondo. Se possibile, mi piacerebbe farlo velocemente come ogni 50 ms o almeno ogni 100 ms.Come eliminare 1 secondo di ritardo nella catena di filtri DirectShow? (Utilizzo di Delphi e DSPACK)

La mia catena di filtri del grafico è costituita da un TFilter mappato al dispositivo di ingresso audio preferito del sistema nella parte superiore. Collego i pin di uscita di quel filtro ai pin di ingresso di un TFilter "WAV Dest" così posso ottenere i campioni in formato WAV PCM. Quindi allego i pin di uscita del filtro "WAV Dest" ai pin di input dell'istanza TSampleGrabber. Cosa devo cambiare per far sì che l'evento TSampleGrabber OnBuffer() si attivi a un intervallo più veloce?


UPDATE: in base alla risposta di Roman R sono stato in grado di implementare una soluzione che sto mostrando qui di seguito. Una nota. Il suo legame mi ha portato al seguente post sul blog che è stato utile per la soluzione:

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; 

risposta

6

suppongo avete bisogno di filtro fine sintonizzarsi Audio Capture per catturare nel buffer della dimensione desiderata, vale a dire abbastanza breve per rendere la latenza complessiva piccola.

I filtri di acquisizione audio espongono l'interfaccia IAMBufferNegotiation sui pin di uscita e SuggestAllocatorProperties consente di specificare la configurazione del buffer.

Vedere per maggiori informazioni: Configuring Windows Media Audio Encoder DMO to reduce delay.

+0

Grazie a @Roman R. Ho aggiornato il mio post originale per includere una soluzione che ho trovato seguendo il tuo collegamento originale. –

Problemi correlati