summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2010-03-03 14:47:35 +0000
committerNanang Izzuddin <nanang@teluu.com>2010-03-03 14:47:35 +0000
commitc2d852485b8591782c9b371f6b277d4a4d0cd35f (patch)
tree05e28702a260ac8d7aa2a03c6835cf1d5c2265f9
parent057b05f79c0a51008e1af1a8487a8277981fc4fb (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.c30
-rw-r--r--pjmedia/src/pjmedia/sound_port.c5
-rw-r--r--pjsip-apps/src/samples/aectest.c22
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));