[Speex-dev] Speex echo canceller on TI C55 DSP
Jim Crichton
jim.crichton at comcast.net
Mon May 8 09:11:59 PDT 2006
Jean-Marc,
I recently started looking at running the echo canceller on a TI C55 DSP
along with the 8kbps narrowband Speex encoder/decoder. This is one of those
"braindead compilers" that you refer to from time to time, and cannot handle
the float struct assignments in the return statements in pseudofloat.h.
Most of these were eliminated in build 11311 (patch by Brian Retford), but
there were four left that I had to break apart. I started with build 11343.
I got several compiler warnings for "shift out of range" in mdf.c, which I
fixed by adding EXTEND32 to all of the SHL32s with 16 bit operands
(st->frame_size in 6 places, st->wtmp2 in 1 place). I have not sent patches
for these two changes, because I still have other problems.
If fftwrap.c, I ifdefed out the spx_fft_float and spx_ifft_float routines,
because there were not used and required smallft.c (which is not so small at
all) to be added to the build.
With these changes, the link was successful, using testecho.c with some
modifications for the C55 environment. The code and data memory
requirements were a lot more than I had hoped (>20kbytes of dynamic data
memory for block size=128, tail length = 1024), and I will probably not be
able to fit it in the production build without some trimming.
When I run the build, it goes into an infinite loop in FLOAT_DIV32 (mdf.c
line 660), which occurs because adapt_rate is < 0, which happens when
FLOAT_EXTRACT16 gets the input {0x7ff0, 0xfffb}. The rounding is causing
the result to go negative. I worked around this by changing
return (a.m+(1<<(-a.e-1)))>>-a.e;
to
return (((spx_uint16_t) a.m)+(1<<(-a.e-1)))>>-a.e;
in FLOAT_EXTRACT16. This changes the returned value from 0xfc00 to 0x400.
Now it runs on for a while, then hits another infinite loop at mdf.c line
641:
st->power_1[i] =
FLOAT_SHL(FLOAT_DIV32_FLOAT(MULT16_32_Q15(M_1,r),FLOAT_MUL32U(e,st->power[i]+10)),WEIGHT_SHIFT+16);
I have not had time to trace this, but it looks like a similar problem,
where the result of MULT16_32_Q15(M_1,r) is negative, and FLOAT_DIV32_FLOAT
bombs. Maybe the best thing to do next is to instrument the routines in
pseudofloat.h which have loops, but I will not get to that for a day or two.
I need to make a decision soon whether to seriously pursue making this work.
With that in mind, here are some questions:
1. speex_echo_state_init takes about 20M instructions, which is a little
frightening, and the calls to speex_echo_cancel take about 630K instructions
for 128 samples. Given your recent experience with the fixed point
canceller, does this sound rational? The MIPs for the canceller are similar
to the MIPs for the encoder running 8kbps, complexity 1.
2. The testecho example uses a frame length and tail size that are powers
of two (128, 1024). Are there any implications to using sizes which are not
powers of two? It would be most convenient to use the encoder frame size
(160), and some multiple of that for the tail size. How does the frame size
affect performance (I understand that the tail length determines what echo
signals are cancelable)?
3. Do you have any suggestions for code/data memory reduction for the
canceller, other than to make the tail length no longer than necessary (this
is a line echo canceller for a local phone, so I should be able to keep it
to 40ms). I was surprised by the size of the FFT code, but I guess that it
is doing much more than the radix2 version in the TI library.
Regards,
Jim Crichton
More information about the Speex-dev
mailing list