📄 mdf.c
字号:
st->X = (spx_word16_t*)speex_alloc((M+1)*N*sizeof(spx_word16_t)); st->Y = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); st->E = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); st->W = (spx_word32_t*)speex_alloc(M*N*sizeof(spx_word32_t)); st->PHI = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t)); st->power = (spx_word32_t*)speex_alloc((frame_size+1)*sizeof(spx_word32_t)); st->power_1 = (spx_float_t*)speex_alloc((frame_size+1)*sizeof(spx_float_t)); st->window = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); st->prop = (spx_word16_t*)speex_alloc(M*sizeof(spx_word16_t)); st->wtmp = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t));#ifdef FIXED_POINT st->wtmp2 = (spx_word16_t*)speex_alloc(N*sizeof(spx_word16_t)); for (i=0;i<N>>1;i++) { st->window[i] = (16383-SHL16(spx_cos(DIV32_16(MULT16_16(25736,i<<1),N)),1)); st->window[N-i-1] = st->window[i]; }#else for (i=0;i<N;i++) st->window[i] = .5-.5*cos(2*M_PI*i/N);#endif for (i=0;i<=st->frame_size;i++) st->power_1[i] = FLOAT_ONE; for (i=0;i<N*M;i++) st->W[i] = 0; { spx_word32_t sum = 0; /* Ratio of ~10 between adaptation rate of first and last block */ spx_word16_t decay = SHR32(spx_exp(NEG16(DIV32_16(QCONST16(2.4,11),M))),1); st->prop[0] = QCONST16(.7, 15); sum = EXTEND32(st->prop[0]); for (i=1;i<M;i++) { st->prop[i] = MULT16_16_Q15(st->prop[i-1], decay); sum = ADD32(sum, EXTEND32(st->prop[i])); } for (i=M-1;i>=0;i--) { st->prop[i] = DIV32(MULT16_16(QCONST16(.8,15), st->prop[i]),sum); } } st->memX=st->memD=st->memE=0; st->preemph = QCONST16(.9,15); if (st->sampling_rate<12000) st->notch_radius = QCONST16(.9, 15); else if (st->sampling_rate<24000) st->notch_radius = QCONST16(.982, 15); else st->notch_radius = QCONST16(.992, 15); st->notch_mem[0] = st->notch_mem[1] = 0; st->adapted = 0; st->Pey = st->Pyy = FLOAT_ONE; st->play_buf = (spx_int16_t*)speex_alloc((PLAYBACK_DELAY+1)*st->frame_size*sizeof(spx_int16_t)); st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; st->play_buf_started = 0; return st;}/** Resets echo canceller state */void speex_echo_state_reset(SpeexEchoState *st){ int i, M, N; st->cancel_count=0; st->screwed_up = 0; N = st->window_size; M = st->M; for (i=0;i<N*M;i++) st->W[i] = 0; for (i=0;i<N*(M+1);i++) st->X[i] = 0; for (i=0;i<=st->frame_size;i++) { st->power[i] = 0; st->power_1[i] = FLOAT_ONE; st->Eh[i] = 0; st->Yh[i] = 0; } for (i=0;i<st->frame_size;i++) { st->last_y[i] = 0; } for (i=0;i<N;i++) { st->E[i] = 0; st->x[i] = 0; } st->notch_mem[0] = st->notch_mem[1] = 0; st->memX=st->memD=st->memE=0; st->saturated = 0; st->adapted = 0; st->sum_adapt = 0; st->Pey = st->Pyy = FLOAT_ONE; for (i=0;i<3*st->frame_size;i++) st->play_buf[i] = 0; st->play_buf_pos = PLAYBACK_DELAY*st->frame_size; st->play_buf_started = 0;}/** Destroys an echo canceller state */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); 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->play_buf); speex_free(st);}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) { speex_echo_cancellation(st, rec, st->play_buf, out); 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]; }}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 */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){ speex_echo_cancellation(st, in, far_end, out);}/** Performs echo cancellation on a frame (deprecated, last arg now ignored) */void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out){ int i,j; int N,M; spx_word32_t Syy,See,Sxx,Sdd; 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; N = st->window_size; M = st->M; 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 filter_dc_notch16(in, st->notch_radius, st->input, st->frame_size, st->notch_mem); /* Copy input data to buffer and apply pre-emphasis */ for (i=0;i<st->frame_size;i++) { spx_word32_t tmp32; st->x[i] = st->x[i+st->frame_size]; tmp32 = SUB32(EXTEND32(far_end[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX)));#ifdef FIXED_POINT /* If saturation occurs here, we need to freeze adaptation for M+1 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[i+st->frame_size] = EXTRACT16(tmp32); st->memX = far_end[i]; tmp32 = SUB32(EXTEND32(st->input[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memD)));#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 = st->input[i]; st->input[i] = tmp32; } /* 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+i] = st->X[j*N+i]; } /* Convert x (far end) to frequency domain */ spx_fft(st->fft_table, st->x, &st->X[0]); #ifdef SMOOTH_BLOCKS spectral_mul_accum(st->X, st->W, st->Y, N, M); spx_ifft(st->fft_table, st->Y, st->e);#endif /* Compute weight gradient */ if (st->saturated == 0) { 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], st->E, st->PHI, N); for (i=0;i<N;i++) st->W[j*N+i] = ADD32(st->W[j*N+i], st->PHI[i]); } } else { st->saturated--; } /* Update weight to prevent circular convolution (MDF / AUMDF) */ for (j=0;j<M;j++) { /* This is a variant of the Alternatively Updated MDF (AUMDF) */ /* Remove the "if" to make this an MDF filter */ if (j==0 || st->cancel_count%(M-1) == j-1) {#ifdef FIXED_POINT for (i=0;i<N;i++) st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16)); spx_ifft(st->fft_table, st->wtmp2, st->wtmp); for (i=0;i<st->frame_size;i++) { st->wtmp[i]=0; } for (i=st->frame_size;i<N;i++) { st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); } spx_fft(st->fft_table, st->wtmp, st->wtmp2); /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ for (i=0;i<N;i++) st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);#else spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); for (i=st->frame_size;i<N;i++) { st->wtmp[i]=0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -