diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2010-03-03 14:47:35 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2010-03-03 14:47:35 +0000 |
commit | c2d852485b8591782c9b371f6b277d4a4d0cd35f (patch) | |
tree | 05e28702a260ac8d7aa2a03c6835cf1d5c2265f9 | |
parent | 057b05f79c0a51008e1af1a8487a8277981fc4fb (diff) |
Ticket #1042, minor updates related to AEC:
- Added requirement of AEC minimal latency between reference and echo in aectest sample app.
- Modified AEC latency in sound port to 3/4 of playback latency.
- Few cleaned up echo_common.c: unused vars, a bit stricter latency check (to be at least as much as PTIME).
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3115 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjmedia/src/pjmedia/echo_common.c | 30 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/sound_port.c | 5 | ||||
-rw-r--r-- | pjsip-apps/src/samples/aectest.c | 22 |
3 files changed, 35 insertions, 22 deletions
diff --git a/pjmedia/src/pjmedia/echo_common.c b/pjmedia/src/pjmedia/echo_common.c index 962e975b..82eec6ea 100644 --- a/pjmedia/src/pjmedia/echo_common.c +++ b/pjmedia/src/pjmedia/echo_common.c @@ -24,6 +24,7 @@ #include <pj/assert.h> #include <pj/list.h> #include <pj/log.h> +#include <pj/math.h> #include <pj/pool.h> #include "echo_internal.h" @@ -46,8 +47,6 @@ struct pjmedia_echo_state ec_operations *op; pj_bool_t lat_ready; /* lat_buf has been filled in. */ - unsigned lat_target_cnt;/* Target number of frames in lat_buf */ - unsigned lat_buf_cnt; /* Actual number of frames in lat_buf */ struct frame lat_buf; /* Frame queue for delayed playback */ struct frame lat_free; /* Free frame list. */ @@ -144,7 +143,7 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool, unsigned options, pjmedia_echo_state **p_echo ) { - unsigned ptime; + unsigned ptime, lat_cnt; pjmedia_echo_state *ec; pj_status_t status; @@ -194,22 +193,21 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool, /* Create latency buffers */ ptime = samples_per_frame * 1000 / clock_rate; - if (latency_ms == 0) { + if (latency_ms > ptime) { + /* Normalize latency with delaybuf/WSOLA latency */ + latency_ms -= PJ_MIN(ptime, PJMEDIA_WSOLA_DELAY_MSEC); + } + if (latency_ms < ptime) { /* Give at least one frame delay to simplify programming */ latency_ms = ptime; } - ec->lat_target_cnt = latency_ms / ptime; - if (ec->lat_target_cnt != 0) { - unsigned i; - for (i=0; i < ec->lat_target_cnt; ++i) { - struct frame *frm; - - frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame<<1) + - sizeof(struct frame)); - pj_list_push_back(&ec->lat_free, frm); - } - } else { - ec->lat_ready = PJ_TRUE; + lat_cnt = latency_ms / ptime; + while (lat_cnt--) { + struct frame *frm; + + frm = (struct frame*) pj_pool_alloc(pool, (samples_per_frame<<1) + + sizeof(struct frame)); + pj_list_push_back(&ec->lat_free, frm); } /* Create delay buffer to compensate drifts */ diff --git a/pjmedia/src/pjmedia/sound_port.c b/pjmedia/src/pjmedia/sound_port.c index 70c71215..1029fc3d 100644 --- a/pjmedia/src/pjmedia/sound_port.c +++ b/pjmedia/src/pjmedia/sound_port.c @@ -563,7 +563,10 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_set_ec( pjmedia_snd_port *snd_port, //since actual input latency should be zero. //delay_ms = (si.rec_latency + si.play_latency) * 1000 / // snd_port->clock_rate; - delay_ms = prm.output_latency_ms; + /* Set EC latency to 3/4 of output latency to reduce the + * possibility of missing/late reference frame. + */ + delay_ms = prm.output_latency_ms * 3/4; status = pjmedia_echo_create2(pool, snd_port->clock_rate, snd_port->channel_count, snd_port->samples_per_frame, diff --git a/pjsip-apps/src/samples/aectest.c b/pjsip-apps/src/samples/aectest.c index 09a745fd..c3e8e0f0 100644 --- a/pjsip-apps/src/samples/aectest.c +++ b/pjsip-apps/src/samples/aectest.c @@ -55,11 +55,19 @@ static const char *desc = " <OUTPUT.WAV> is the output file to store the test result \n" "\n" " options:\n" -" -d The delay between playback and capture in ms. Default is zero.\n" +" -d The delay between playback and capture in ms, at least 25 ms.\n" +" Default is 25 ms. See note below. \n" " -l Set the echo tail length in ms. Default is 200 ms \n" " -r Set repeat count (default=1) \n" " -a Algorithm: 0=default, 1=speex, 3=echo suppress \n" -" -i Interactive \n"; +" -i Interactive \n" +"\n" +" Note that for the AEC internal buffering mechanism, it is required\n" +" that the echoed signal (in REC.WAV) is delayed from the \n" +" corresponding reference signal (in PLAY.WAV) at least as much as \n" +" frame time + PJMEDIA_WSOLA_DELAY_MSEC. In this application, frame \n" +" time is 20 ms and default PJMEDIA_WSOLA_DELAY_MSEC is 5 ms, hence \n" +" 25 ms delay is the minimum value. \n"; /* * Sample session: @@ -91,7 +99,7 @@ int main(int argc, char *argv[]) pjmedia_echo_state *ec; pjmedia_frame play_frame, rec_frame; unsigned opt = 0; - unsigned latency_ms = 0; + unsigned latency_ms = 25; unsigned tail_ms = TAIL_LENGTH; pj_timestamp t0, t1; int i, repeat=1, interactive=0, c; @@ -101,6 +109,10 @@ int main(int argc, char *argv[]) switch (c) { case 'd': latency_ms = atoi(pj_optarg); + if (latency_ms < 25) { + puts("Invalid delay"); + puts(desc); + } break; case 'l': tail_ms = atoi(pj_optarg); @@ -127,7 +139,7 @@ int main(int argc, char *argv[]) case 'r': repeat = atoi(pj_optarg); if (repeat < 1) { - puts("Invalid algorithm"); + puts("Invalid repeat count"); puts(desc); return 1; } @@ -251,7 +263,7 @@ int main(int argc, char *argv[]) } pj_get_timestamp(&t1); - i = pjmedia_wav_writer_port_get_pos(wav_out) * 1000 / + i = pjmedia_wav_writer_port_get_pos(wav_out) / sizeof(pj_int16_t) * 1000 / (wav_out->info.clock_rate * wav_out->info.channel_count); PJ_LOG(3,(THIS_FILE, "Processed %3d.%03ds audio", i / 1000, i % 1000)); |