0

I am attempting to use the speex libraries acoustic echo cancellation facilities like so:

// Setup
int sample_rate = NF_DRIVER_SAMPLERATE;
for (int i = 0; i < NF_DRIVER_CHANNELS; ++i) {
    _echo_state[i] = speex_echo_state_init(NF_DRIVER_SAMPLE_BLOCK_SIZE, NF_DRIVER_SAMPLE_BLOCK_SIZE * 8);
    _preprocess_state[i] = speex_preprocess_state_init(NF_DRIVER_SAMPLE_BLOCK_SIZE, sample_rate);
    speex_echo_ctl(_echo_state[i], SPEEX_ECHO_SET_SAMPLING_RATE, &sample_rate);
    speex_preprocess_ctl(_preprocess_state[i], SPEEX_PREPROCESS_SET_ECHO_STATE, _echo_state[i]);
}
// Run
for (int i = 0; i < NF_DRIVER_CHANNELS; ++i) {
        spx_int16_t ref_buffer[NF_DRIVER_SAMPLE_BLOCK_SIZE];
        spx_int16_t echo_buffer[NF_DRIVER_SAMPLE_BLOCK_SIZE];
        spx_int16_t out_buffer[NF_DRIVER_SAMPLE_BLOCK_SIZE];
        for (int j = 0; j < NF_DRIVER_SAMPLE_BLOCK_SIZE; ++j) {
            ref_buffer[j] = static_cast<spx_int16_t>(current_samples[(j * NF_DRIVER_CHANNELS) + i] * std::numeric_limits<spx_int16_t>::max());
        }
        for (int j = 0; j < NF_DRIVER_SAMPLE_BLOCK_SIZE; ++j) {
            echo_buffer[j] = static_cast<spx_int16_t>(other_samples[(j * NF_DRIVER_CHANNELS) + i] * std::numeric_limits<spx_int16_t>::max());
        }
        speex_echo_cancellation(_echo_state[i], ref_buffer, echo_buffer, out_buffer);
        speex_preprocess_run(_preprocess_state[i], out_buffer);
        for (int j = 0; j < NF_DRIVER_SAMPLE_BLOCK_SIZE; ++j) {
            other_samples[(j * NF_DRIVER_CHANNELS) + i] += static_cast<float>(out_buffer[j]) / static_cast<float>(std::numeric_limits<spx_int16_t>::max());
        }
    }

Unfortunately I am getting a lot of stack corruption when calling speex_echo_cancellation which causes a lot of unexpected errors. In this case the samplerate is 44.1kHz, the channels are 2 and the block size is 1024. I also see a lot of warnings from speex that print the following:

warning: The echo canceller started acting funny and got slapped (reset). It swears it will behave now.

I am unclear where I am going wrong. I have tried setting the filter length to a number of different sizes, even feeding it just 0's as samples, but it always seems to leak. Would anyone know what the issue is?

I should add that I have tried not reading from "current_samples" and "other_samples" so the issue is solely reproducible by running the speex calls in the Run section of the code.

4

0 回答 0