零延迟麦克风环回,侧音

时间:2015-06-23 19:18:50

标签: c++ windows audio portaudio

我正在尝试以编程方式创建一个零延迟麦克风环回到扬声器或输出。这用于生成耳机的侧音。正如我确信任何读者都知道的那样,侧音必须是零延迟,否则,听到你的延迟会导致你失去大部分连贯的说话能力。

我尝试使用C#中的Naudio和使用C ++的portaudio创建解决方案。我对PortAudio有最好的运气,但是我无法实现我需要的零延迟侧标。 Portaudio产生5ms左右的延迟,这是可以检测到的,并导致我的语音持续减慢。

我知道windows提供了一个麦克风环回,我已经测试了这个,但是即使windows环回也有足够的延迟来作为侧音来讨厌。

我在两个部分提出我的问题

1。)这是硬件/软件的限制,实现零音频延迟几乎无法克服吗?

2.。)这是我使用portaudio的C ++代码。有没有办法比我已经有更多的减少延迟? (请原谅我可能邋code的代码,我对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);
}

1 个答案:

答案 0 :(得分:0)

抽象层只能增加延迟,而不能减少延迟。很明显,时间旅行是不可能的。 PulseAudio不是Windows上的本机API,它建立在原生音频架构之上。

当前的本机Windows API是WASAPI。它具有低延迟的良好声誉。但它也是底层硬件的抽象层。例如USB也有延迟。你不能做得更好。