2015-06-23 68 views
1

我試圖以編程方式爲揚聲器或輸出創建零延遲麥克風環回。這用於爲耳機生成側音。正如我確信任何讀者都知道的那樣,側音必須是零延遲,否則,聽到自己的延遲會導致你失去大部分連貫的說話能力。零延遲麥克風環回,側音

我試着在C#中使用Naudio和使用C++的portaudio創建解決方案。我對PortAudio有最好的運氣,但是我無法實現我需要的零延遲側音。 Portaudio產生了5毫秒左右的延遲,這是可檢測的,並導致我的講話持續減慢。

我知道windows提供麥克風環回,而我已經測試過這個,但是即使窗口環回有足夠的延遲時間也會成爲側音惱人的。

我問我在兩個部分

1)問題是這樣的硬件/軟件的限制,並實現零的音頻等待幾乎難以逾越?

2.)這是我使用portaudio的C++代碼。有什麼方法可以減少比我已有的延遲更多嗎? (請原諒我可能馬虎的代碼,我很新的C++和我仍然在學習)

class vC_sidetone { 
public: 
    void enable(int in_ch, int out_ch); 
    void disable(); 

    vC_sidetone(int inputDevice, int outputDevice){ 
     st_inputDevice = inputDevice; 
     st_outputDevice = outputDevice; 
    } 

    int st_instanceCallBack(const void *inputBuffer, 
     void *outputBuffer, 
     unsigned long framesPerBuffer, 
     const PaStreamCallbackTimeInfo *timeInfo, 
     PaStreamCallbackFlags statusFlags); 

private: 
    int st_inputDevice; 
    int st_outputDevice; 
    PaError st_error; 
    PaStream *st_stream = NULL; 
}; 

PaStreamParameters vC_getParam(PaDeviceIndex dev, int ch, PaSampleFormat smplFormat){ 

    PaStreamParameters param; 
    param.device = dev; 
    param.channelCount = ch; 
    param.sampleFormat = smplFormat; 
    //param.suggestedLatency = Pa_GetDeviceInfo(dev)->defaultLowInputLatency; 
    param.suggestedLatency = 0.000; //here is a good place to tweak latency 
    param.hostApiSpecificStreamInfo = NULL; 

    return param; 
} 

void vC_sidetone::enable(int in_ch, int out_ch){ 
    int framesPerBuffer = 1; 
    PaSampleFormat smplFormat = paFloat32; 
    int smplRate = 44100; 

    PaStreamParameters inParam = vC_getParam(st_inputDevice, in_ch, smplFormat); 
    PaStreamParameters outParam = vC_getParam(st_outputDevice, out_ch, smplFormat); 

    st_error = Pa_Initialize(); 

    // Open and start stream using callback: 
    st_error = Pa_OpenStream(
     &st_stream, 
     &inParam, 
     &outParam, 
     smplRate, 
     framesPerBuffer, 
     paClipOff, 
     st_gblCallBack, 
     this 
     ); 

    st_error = Pa_StartStream(st_stream); 
} 

void vC_sidetone::disable(){ 

    st_error = Pa_StopStream(st_stream); 
    Pa_AbortStream(st_stream); 
    Pa_CloseStream(st_stream); 
    Pa_Terminate(); 
} 

int vC_sidetone::st_instanceCallBack(const void *inputBuffer, 
          void *outputBuffer, 
          unsigned long framesPerBuffer, 
          const PaStreamCallbackTimeInfo *timeInfo, 
          PaStreamCallbackFlags statusFlags){ 

    (void)timeInfo; // Prevent unused variable warnings. 
    (void)statusFlags; 


    // Cast data to floats: 
    float *out = (float*)outputBuffer; 
    float *in = (float*)inputBuffer; 
    unsigned long i; 

    //for (i = 0; i < framesPerBuffer*NUM_CHANNELS; i++) 
    // out[i] = in[i]; 
    for (i = 0; i < framesPerBuffer; i++) //another good place for latency 
     out[i] = in[i]; 

    return paContinue; 
} 

//this is actually not part of the vC_sidetone class, I was getting linker errors 
static int st_gblCallBack(const void *inputBuffer, 
    void *outputBuffer, 
    unsigned long framesPerBuffer, 
    const PaStreamCallbackTimeInfo *timeInfo, 
    PaStreamCallbackFlags statusFlags, 
    void *userData){ 

    return ((vC_sidetone*)userData)->st_instanceCallBack(inputBuffer, outputBuffer, 
     framesPerBuffer, 
     timeInfo, 
     statusFlags); 
} 
+0

由於輸入和輸出硬件和底層軟件棧(不是PortAudio,但是DirectSound或任何它使用的)的工作方式,你所需要的通常是不可實現的。數據在大小大於1的緩衝區中傳遞,每個樣本需要1/44000秒。因此,例如,只有88個採樣的緩衝器意味着用於回放(並且再次用於記錄)的最小2ms延遲。關於Q2,PortAudio文檔建議您將framesPerBuffer設置爲零以避免增加延遲的額外緩衝層。 – Damon

回答

0

抽象層只能增加延遲,而不是降低它。很明顯,時間旅行是不可能的。 PulseAudio不是Windows上的本地API,它建立在本機音頻體系結構之上。

當前的本機Windows API是WASAPI。它具有低延遲的良好聲譽。但它也是底層硬件的抽象層。 USB也有延遲。你不能做得比這更好。