Загрузка данных
EXPORT void speex_echo_state_destroy(SpeexEchoState *st)
{
spx_fft_destroy(st->fft_table);
speex_free(st->e);
speex_free(st->x);
speex_free(st->input);
speex_free(st->y);
speex_free(st->last_y);
speex_free(st->Yf);
speex_free(st->Rf);
speex_free(st->Xf);
speex_free(st->Yh);
speex_free(st->Eh);
speex_free(st->X);
speex_free(st->Y);
speex_free(st->E);
speex_free(st->W);
#ifdef TWO_PATH
speex_free(st->foreground);
#endif
speex_free(st->PHI);
speex_free(st->power);
speex_free(st->power_1);
speex_free(st->window);
speex_free(st->prop);
speex_free(st->wtmp);
#ifdef FIXED_POINT
speex_free(st->wtmp2);
#endif
speex_free(st->memX);
speex_free(st->memD);
speex_free(st->memE);
speex_free(st->notch_mem);
speex_free(st->play_buf);
speex_free(st);
#ifdef DUMP_ECHO_CANCEL_DATA
fclose(rFile);
fclose(pFile);
fclose(oFile);
rFile = pFile = oFile = NULL;
#endif
}
EXPORT void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out)
{
int i;
/*speex_warning_int("capture with fill level ", st->play_buf_pos/st->frame_size);*/
st->play_buf_started = 1;
if (st->play_buf_pos>=st->frame_size)
{
#if 1//def MY_CODE
speex_echo_cancellation(st, rec, st->play_buf, out);
#else
for (i=0;i<st->frame_size;i++)
out[i] = rec[i];
#endif
st->play_buf_pos -= st->frame_size;
for (i=0;i<st->play_buf_pos;i++)
st->play_buf[i] = st->play_buf[i+st->frame_size];
} else {
speex_warning("No playback frame available (your application is buggy and/or got xruns)");
if (st->play_buf_pos!=0)
{
speex_warning("internal playback buffer corruption?");
st->play_buf_pos = 0;
}
for (i=0;i<st->frame_size;i++)
out[i] = rec[i];
}
}
EXPORT void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play)
{
/*speex_warning_int("playback with fill level ", st->play_buf_pos/st->frame_size);*/
if (!st->play_buf_started)
{
speex_warning("discarded first playback frame");
return;
}
if (st->play_buf_pos<=PLAYBACK_DELAY*st->frame_size)
{
int i;
for (i=0;i<st->frame_size;i++)
st->play_buf[st->play_buf_pos+i] = play[i];
st->play_buf_pos += st->frame_size;
if (st->play_buf_pos <= (PLAYBACK_DELAY-1)*st->frame_size)
{
speex_warning("Auto-filling the buffer (your application is buggy and/or got xruns)");
for (i=0;i<st->frame_size;i++)
st->play_buf[st->play_buf_pos+i] = play[i];
st->play_buf_pos += st->frame_size;
}
} else {
speex_warning("Had to discard a playback frame (your application is buggy and/or got xruns)");
}
}
/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */
EXPORT void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out, spx_int32_t *Yout)
{
printf("%s(%d)\n",__FUNCTION__,__LINE__);
speex_echo_cancellation(st, in, far_end, out);
}
/** Performs echo cancellation on a frame */
EXPORT void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out)
{
int i,j, chan, speak;
int N,M, C, K;
spx_word32_t Syy,See,Sxx,Sdd, Sff;
#ifdef TWO_PATH
spx_word32_t Dbf;
int update_foreground;
#endif
spx_word32_t Sey;
spx_word16_t ss, ss_1;
spx_float_t Pey = FLOAT_ONE, Pyy=FLOAT_ONE;
spx_float_t alpha, alpha_1;
spx_word16_t RER;
spx_word32_t tmp32;
//printf("%s(%d)\n",__FUNCTION__,__LINE__);
N = st->window_size;
M = st->M;
C = st->C;
K = st->K;
st->cancel_count++;
#ifdef FIXED_POINT
ss=DIV32_16(11469,M);
ss_1 = SUB16(32767,ss);
#else
ss=.35/M;
ss_1 = 1-ss;
#endif
for (chan = 0; chan < C; chan++)
{
/* Apply a notch filter to make sure DC doesn't end up causing problems */
filter_dc_notch16(in+chan, st->notch_radius, st->input+chan*st->frame_size, st->frame_size, st->notch_mem+2*chan, C);
/* Copy input data to buffer and apply pre-emphasis */
/* Copy input data to buffer */
for (i=0;i<st->frame_size;i++)
{
spx_word32_t tmp32;
/* FIXME: This core has changed a bit, need to merge properly */
tmp32 = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD[chan])));
#ifdef FIXED_POINT
if (tmp32 > 32767)
{
tmp32 = 32767;
if (st->saturated == 0)
st->saturated = 1;
}
if (tmp32 < -32767)
{
tmp32 = -32767;
if (st->saturated == 0)
st->saturated = 1;
}
#endif
st->memD[chan] = st->input[chan*st->frame_size+i];
st->input[chan*st->frame_size+i] = EXTRACT16(tmp32);
}
}
for (speak = 0; speak < K; speak++)
{
for (i=0;i<st->frame_size;i++)
{
spx_word32_t tmp32;
st->x[speak*N+i] = st->x[speak*N+i+st->frame_size];
tmp32 = SUB32(EXTEND32(far_end[i*K+speak]), EXTEND32(MULT16_16_P15(st->preemph, st->memX[speak])));
#ifdef FIXED_POINT
/*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */
if (tmp32 > 32767)
{
tmp32 = 32767;
st->saturated = M+1;
}
if (tmp32 < -32767)
{
tmp32 = -32767;
st->saturated = M+1;
}
#endif
st->x[speak*N+i+st->frame_size] = EXTRACT16(tmp32);
st->memX[speak] = far_end[i*K+speak];
}
}
for (speak = 0; speak < K; speak++)
{
/* Shift memory: this could be optimized eventually*/
for (j=M-1;j>=0;j--)
{
for (i=0;i<N;i++)
st->X[(j+1)*N*K+speak*N+i] = st->X[j*N*K+speak*N+i];
}
/* Convert x (echo input) to frequency domain */
spx_fft(st->fft_table, st->x+speak*N, &st->X[speak*N]);
}
Sxx = 0;
for (speak = 0; speak < K; speak++)
{
Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);
power_spectrum_accum(st->X+speak*N, st->Xf, N);
}
Sff = 0;
for (chan = 0; chan < C; chan++)
{
#ifdef TWO_PATH
/* Compute foreground filter */
spectral_mul_accum16(st->X, st->foreground+chan*N*K*M, st->Y+chan*N, N, M*K);
spx_ifft(st->fft_table, st->Y+chan*N, st->e+chan*N);
for (i=0;i<st->frame_size;i++)
st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->e[chan*N+i+st->frame_size]);
Sff += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);
#endif
}
/* Adjust proportional adaption rate */
/* FIXME: Adjust that for C, K*/
if (st->adapted)
mdf_adjust_prop (st->W, N, M, C*K, st->prop);
/* Compute weight gradient */
if (st->saturated == 0)
{
for (chan = 0; chan < C; chan++)
{
for (speak = 0; speak < K; speak++)
{
for (j=M-1;j>=0;j--)
{
weighted_spectral_mul_conj(st->power_1, FLOAT_SHL(PSEUDOFLOAT(st->prop[j]),-15), &st->X[(j+1)*N*K+speak*N], st->E+chan*N, st->PHI, N);
for (i=0;i<N;i++)
st->W[chan*N*K*M + j*N*K + speak*N + i] += st->PHI[i];
}
}
}
} else {
st->saturated--;
}