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.