int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { if (!is_component_enabled()) { return apm_->kNoError; } assert(audio->samples_per_split_channel() <= 160); assert(audio->num_channels() == apm_->num_reverse_channels()); int err = apm_->kNoError; // The ordering convention must be followed to pass to the correct AEC. size_t handle_index = 0; for (int i = 0; i < apm_->num_output_channels(); i++) { for (int j = 0; j < audio->num_channels(); j++) { Handle* my_handle = static_cast<Handle*>(handle(handle_index)); err = WebRtcAec_BufferFarend( my_handle, audio->low_pass_split_data(j), static_cast<WebRtc_Word16>(audio->samples_per_split_channel())); if (err != apm_->kNoError) { return GetHandleError(my_handle); // TODO(ajm): warning possible? } handle_index++; } } return apm_->kNoError; }
int speex_aec_playback_for_async(int16_t* farend, float snd_amplification) { int ret_val = -1; switch(aec_core_used) { #ifdef WEBRTC_AEC_CORE_ENABLED case WEBRTC_AEC: if(webrtc_aec_pty.webrtc_aec) ret_val = WebRtcAec_BufferFarend(webrtc_aec_pty.webrtc_aec, farend, webrtc_aec_pty.frame_size); break; case WEBRTC_AECM: if(webrtc_aecm_pty.webrtc_aec) ret_val = WebRtcAecm_BufferFarend(webrtc_aecm_pty.webrtc_aec, farend, webrtc_aecm_pty.frame_size); break; #endif case SPEEX_AEC: default: if(speex_aec_pty.speex_echo_state) { speex_echo_playback((SpeexEchoState*)speex_aec_pty.speex_echo_state, farend); // speex_preprocess_run((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state_tmp, farend); ret_val = 0; } break; } if(snd_amplification != 1.0f && snd_amplification > 0) { for(int i=0; i<speex_aec_pty.frame_size; ++i) farend[i] = farend[i]*snd_amplification; } return ret_val; }
int pass_audio_output(Filter_Audio *f_a, const int16_t *data, unsigned int samples) { if (!f_a || (!f_a->echo_enabled && !f_a->gain_enabled)) { return -1; } unsigned int nsx_samples = f_a->fs / 100; if (!samples || (samples % nsx_samples) != 0) { return -1; } _Bool resample = 0; unsigned int resampled_samples = 0; if (f_a->fs != 16000) { samples = (samples / nsx_samples) * 160; nsx_samples = 160; resample = 1; } unsigned int temp_samples = samples; float *d_f = (float *)STACK_ALLOC( nsx_samples * sizeof(float) + nsx_samples * sizeof(int16_t) ); while (temp_samples) { if (resample) { int16_t *d = (int16_t *)(d_f + nsx_samples); downsample_audio_echo_in(f_a, d, data + resampled_samples); if (WebRtcAgc_AddFarend(f_a->gain_control, d, nsx_samples) == -1) return -1; S16ToFloatS16(d, nsx_samples, d_f); resampled_samples += f_a->fs / 100; } else { S16ToFloatS16(data + (samples - temp_samples), nsx_samples, d_f); } if (WebRtcAec_BufferFarend(f_a->echo_cancellation, d_f, nsx_samples) == -1) { return -1; } temp_samples -= nsx_samples; } return 0; }
int KotiAEC_process(const int16_t* farend, const int16_t* nearend, int16_t* out) { int ret = -1, i = 0, frame_size = 0; switch(aec_core_used) { #ifdef WEBRTC_AEC_CORE_ENABLED case WEBRTC_AEC: if(farend) WebRtcAec_BufferFarend(webrtc_aec_pty.webrtc_aec, farend, webrtc_aec_pty.frame_size); if(!WebRtcAec_Process(webrtc_aec_pty.webrtc_aec, nearend, NULL, out, NULL, webrtc_aec_pty.frame_size, webrtc_aec_pty.sndcard_delay_ms, 0)) { ret = 0; } if(webrtc_aec_pty.webrtc_ns) { WebRtcNsx_Process((NsxHandle*)webrtc_aec_pty.webrtc_ns, out, NULL, out, NULL); if(webrtc_aec_pty.frame_size == 160) WebRtcNsx_Process((NsxHandle*)webrtc_aec_pty.webrtc_ns, out+80, NULL, out+80, NULL); } if(webrtc_aec_pty.webrtc_agc) { int32_t out_c; uint8_t warn_status; WebRtcAgc_Process(webrtc_aec_pty.webrtc_agc, out, NULL, webrtc_aec_pty.frame_size, out, NULL, 32, &out_c, 1, &warn_status); } // if(webrtc_aec_pty.webrtc_ns) // { // WebRtcNsx_Process((NsxHandle*)webrtc_aec_pty.webrtc_ns, out, NULL, out, NULL); // if(webrtc_aec_pty.frame_size == 160) // WebRtcNsx_Process((NsxHandle*)webrtc_aec_pty.webrtc_ns, out+80, NULL, out+80, NULL); // } frame_size = webrtc_aec_pty.frame_size; break; case WEBRTC_AECM: /* if(farend) WebRtcAecm_BufferFarend(webrtc_aecm_pty.webrtc_aec, farend, webrtc_aecm_pty.frame_size); if(!WebRtcAecm_Process(webrtc_aecm_pty.webrtc_aec, nearend, NULL, out, webrtc_aecm_pty.frame_size, webrtc_aecm_pty.sndcard_delay_ms)) { ret = 0; } */ memcpy(proc_tmp_buf, nearend, webrtc_aecm_pty.frame_size*2); if(webrtc_aecm_pty.webrtc_ns) { WebRtcNsx_Process((NsxHandle*)webrtc_aecm_pty.webrtc_ns, proc_tmp_buf, NULL, proc_tmp_buf, NULL); if(webrtc_aecm_pty.frame_size == 160) WebRtcNsx_Process((NsxHandle*)webrtc_aecm_pty.webrtc_ns, proc_tmp_buf+80, NULL, proc_tmp_buf+80, NULL); } if(webrtc_aecm_pty.webrtc_agc) { int32_t out_c; uint8_t warn_status; WebRtcAgc_Process(webrtc_aecm_pty.webrtc_agc, proc_tmp_buf, NULL, webrtc_aecm_pty.frame_size, proc_tmp_buf, NULL, 32, &out_c, 1, &warn_status); } // AEC if(farend) WebRtcAecm_BufferFarend(webrtc_aecm_pty.webrtc_aec, farend, webrtc_aecm_pty.frame_size); if(!WebRtcAecm_Process(webrtc_aecm_pty.webrtc_aec, proc_tmp_buf, NULL, out, webrtc_aecm_pty.frame_size, webrtc_aecm_pty.sndcard_delay_ms)) { ret = 0; } frame_size = webrtc_aecm_pty.frame_size; break; #endif case SPEEX_AEC: default: #ifdef OLD_SPEEX_AEC speex_echo_cancel((SpeexEchoState*)speex_aec_pty.speex_echo_state, nearend, farend, out, speex_aec_pty.nosie); if(speex_preprocess((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, out, speex_aec_pty.nosie) == 1) ret = 0; #else if(farend) speex_echo_cancellation((SpeexEchoState*)speex_aec_pty.speex_echo_state, nearend, farend, out); else speex_echo_capture((SpeexEchoState*)speex_aec_pty.speex_echo_state, nearend, out); // speex_preprocess_estimate_update((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, out); if(speex_preprocess_run((SpeexPreprocessState*)speex_aec_pty.speex_preprocess_state, out) == 1) ret = 0; #endif frame_size = speex_aec_pty.frame_size; break; } // if the output sound needed amplify if(output_sound_amplification != 1.0f && output_sound_amplification > 0) { for(; i<frame_size; ++i) out[i] = out[i]*output_sound_amplification; } return ret; }