static void wiener_denoise(WMAVoiceContext *s, int fcb_type, float *synth_pf, int size, const float *lpcs) { int remainder, lim, n; if (fcb_type != FCB_TYPE_SILENCE) { float *tilted_lpcs = s->tilted_lpcs_pf, *coeffs = s->denoise_coeffs_pf, tilt_mem = 0; tilted_lpcs[0] = 1.0; memcpy(&tilted_lpcs[1], lpcs, sizeof(lpcs[0]) * s->lsps); memset(&tilted_lpcs[s->lsps + 1], 0, sizeof(tilted_lpcs[0]) * (128 - s->lsps - 1)); ff_tilt_compensation(&tilt_mem, 0.7 * tilt_factor(lpcs, s->lsps), tilted_lpcs, s->lsps + 2); /* The IRDFT output (127 samples for 7-bit filter) beyond the frame * size is applied to the next frame. All input beyond this is zero, * and thus all output beyond this will go towards zero, hence we can * limit to min(size-1, 127-size) as a performance consideration. */ remainder = FFMIN(127 - size, size - 1); calc_input_response(s, tilted_lpcs, fcb_type, coeffs, remainder); /* apply coefficients (in frequency spectrum domain), i.e. complex * number multiplication */ memset(&synth_pf[size], 0, sizeof(synth_pf[0]) * (128 - size)); ff_rdft_calc(&s->rdft, synth_pf); ff_rdft_calc(&s->rdft, coeffs); synth_pf[0] *= coeffs[0]; synth_pf[1] *= coeffs[1]; for (n = 1; n < 128; n++) { float v1 = synth_pf[n * 2], v2 = synth_pf[n * 2 + 1]; synth_pf[n * 2] = v1 * coeffs[n * 2] - v2 * coeffs[n * 2 + 1]; synth_pf[n * 2 + 1] = v2 * coeffs[n * 2] + v1 * coeffs[n * 2 + 1]; } ff_rdft_calc(&s->irdft, synth_pf); } /* merge filter output with the history of previous runs */ if (s->denoise_filter_cache_size) { lim = FFMIN(s->denoise_filter_cache_size, size); for (n = 0; n < lim; n++) synth_pf[n] += s->denoise_filter_cache[n]; s->denoise_filter_cache_size -= lim; memmove(s->denoise_filter_cache, &s->denoise_filter_cache[size], sizeof(s->denoise_filter_cache[0]) * s->denoise_filter_cache_size); } /* move remainder of filter output into a cache for future runs */ if (fcb_type != FCB_TYPE_SILENCE) { lim = FFMIN(remainder, s->denoise_filter_cache_size); for (n = 0; n < lim; n++) s->denoise_filter_cache[n] += synth_pf[size + n]; if (lim < remainder) { memcpy(&s->denoise_filter_cache[lim], &synth_pf[size + lim], sizeof(s->denoise_filter_cache[0]) * (remainder - lim)); s->denoise_filter_cache_size = remainder; } } }