123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- #include "precompile.h"
- #include "audioaec.h"
- #include "audioengine.h"
- #include <speex/speex_echo.h>
- static apr_status_t read_frame(void *self, audioframe_t *frame)
- {
- audioaec_t *aec = CONTAINING_RECORD(self, audioaec_t, base);
- apr_status_t status = APR_SUCCESS;
-
- if (aec->opt & AUDIO_AEC_OPT_READ_AS_CAPTURE) {
- aec->tmp_capture_frame.size = SUGGEST_FRAME_SIZE;
- status = aec->base.downstream->vtbl->read_frame(aec->base.downstream, &aec->tmp_capture_frame);
- if (status == 0) {
- if (aec->tmp_capture_frame.size == 0) {
- memset(aec->tmp_capture_frame.buffer, 0, aec->psize);
- }
- frame->dtmf = aec->tmp_capture_frame.dtmf;
- frame->size = aec->psize;
- speex_echo_capture(aec->state, (short*)aec->tmp_capture_frame.buffer, (short*)frame->buffer);
- }
- } else {
- status = aec->base.downstream->vtbl->read_frame(aec->base.downstream, frame);
- if (status != 0 || frame->size == 0) {
- memset(frame->buffer, 0, aec->psize);
- frame->size = aec->psize;
- }
- speex_echo_playback(aec->state, (short*)frame->buffer);
- }
- return status;
- }
- static apr_status_t write_frame(void *self, const audioframe_t *frame)
- {
- audioaec_t *aec = CONTAINING_RECORD(self, audioaec_t, base);
- apr_status_t status = APR_SUCCESS;
- if (aec->opt & AUDIO_AEC_OPT_READ_AS_CAPTURE) {
- aec->tmp_capture_frame.dtmf = frame->dtmf;
- if (frame->size == 0) {
- aec->tmp_capture_frame.size = aec->psize;
- memset(aec->tmp_capture_frame.buffer, 0, aec->psize);
- speex_echo_playback(aec->state, (short*)aec->tmp_capture_frame.buffer);
- status = aec->base.downstream->vtbl->write_frame(aec->base.downstream, &aec->tmp_capture_frame);
- } else {
- speex_echo_playback(aec->state, (short*)frame->buffer);
- status = aec->base.downstream->vtbl->write_frame(aec->base.downstream, frame);
- }
- } else {
- if (frame->size == 0) {
- memset((void*)frame->buffer, 0, aec->psize); // because size is zero, so buffer can be use
- }
- aec->tmp_capture_frame.dtmf = frame->dtmf;
- aec->tmp_capture_frame.size = aec->psize;
- speex_echo_capture(aec->state, (short*)frame->buffer, (short*)aec->tmp_capture_frame.buffer);
- status = aec->base.downstream->vtbl->write_frame(aec->base.downstream, &aec->tmp_capture_frame);
- }
- return status;
- }
- static audiostream_vtbl_t g_stream_vtbl = {
- &read_frame,
- &write_frame,
- };
- apr_status_t audioaec_create(apr_pool_t *pool, audioengine_t *engine, int clock, int ptime, int opt, int latency, audioaec_t **p_aec)
- {
- audioaec_t *aec;
- if (latency == 0)
- latency = 300;
- aec = apr_palloc(pool, sizeof(audioaec_t));
- memset(aec, 0, sizeof(audioaec_t));
- audiostream_init(engine, &g_stream_vtbl, &aec->base);
- aec->opt = opt;
- aec->clock = clock;
- aec->ptime = ptime;
- aec->psize = ptime * clock / 1000 * 2;
- aec->tmp_capture_frame.size = SUGGEST_FRAME_SIZE;
- aec->tmp_capture_frame.buffer = apr_palloc(pool, SUGGEST_FRAME_SIZE);
- aec->tmp_capture_frame.dtmf = 0;
- /* Set EC latency to 3/4 of output latency to reduce the
- * possibility of missing/late reference frame.
- */
- {
- //unsigned uLlatency = 440 * 3/4;
- int uLlatency = latency * 3 / 4;
- aec->state = speex_echo_state_init(ptime * clock /1000,clock * uLlatency / 1000);
- }
-
- *p_aec = aec;
- return APR_SUCCESS;
- }
- void audioaec_destroy(audioaec_t *aec)
- {
- speex_echo_state_destroy(aec->state);
- }
|