From 3d85892052607fda3da8e2b3f8958982e669b22e Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 11 Aug 2023 17:40:46 +0200 Subject: [PATCH] avfilter/af_adeclick: fix window generation Stops adding invalid sinusoids in overlap-add mode. --- libavfilter/af_adeclick.c | 64 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/libavfilter/af_adeclick.c b/libavfilter/af_adeclick.c index 822f3065b8..328c347b36 100644 --- a/libavfilter/af_adeclick.c +++ b/libavfilter/af_adeclick.c @@ -20,6 +20,7 @@ #include "libavutil/audio_fifo.h" #include "libavutil/opt.h" +#include "libavutil/tx.h" #include "avfilter.h" #include "audio.h" #include "filters.h" @@ -131,9 +132,66 @@ static int config_input(AVFilterLink *inlink) s->window_func_lut = av_calloc(s->window_size, sizeof(*s->window_func_lut)); if (!s->window_func_lut) return AVERROR(ENOMEM); - for (i = 0; i < s->window_size; i++) - s->window_func_lut[i] = sin(M_PI * i / s->window_size) * - (1. - (s->overlap / 100.)) * M_PI_2; + + { + double *tx_in[2], *tx_out[2]; + AVTXContext *tx, *itx; + av_tx_fn tx_fn, itx_fn; + int ret, tx_size; + double scale; + + tx_size = 1 << (32 - ff_clz(s->window_size)); + + scale = 1.0; + ret = av_tx_init(&tx, &tx_fn, AV_TX_DOUBLE_RDFT, 0, tx_size, &scale, 0); + if (ret < 0) + return ret; + + scale = 1.0 / tx_size; + ret = av_tx_init(&itx, &itx_fn, AV_TX_DOUBLE_RDFT, 1, tx_size, &scale, 0); + if (ret < 0) + return ret; + + tx_in[0] = av_calloc(tx_size + 2, sizeof(*tx_in[0])); + tx_in[1] = av_calloc(tx_size + 2, sizeof(*tx_in[1])); + tx_out[0] = av_calloc(tx_size + 2, sizeof(*tx_out[0])); + tx_out[1] = av_calloc(tx_size + 2, sizeof(*tx_out[1])); + if (!tx_in[0] || !tx_in[1] || !tx_out[0] || !tx_out[1]) + return AVERROR(ENOMEM); + + for (int n = 0; n < s->window_size - s->hop_size; n++) + tx_in[0][n] = 1.0; + + for (int n = 0; n < s->hop_size; n++) + tx_in[1][n] = 1.0; + + tx_fn(tx, tx_out[0], tx_in[0], sizeof(double)); + tx_fn(tx, tx_out[1], tx_in[1], sizeof(double)); + + for (int n = 0; n <= tx_size/2; n++) { + double re0 = tx_out[0][2*n]; + double im0 = tx_out[0][2*n+1]; + double re1 = tx_out[1][2*n]; + double im1 = tx_out[1][2*n+1]; + + tx_in[0][2*n] = re0 * re1 - im0 * im1; + tx_in[0][2*n+1] = re0 * im1 + re1 * im0; + } + + itx_fn(itx, tx_out[0], tx_in[0], sizeof(AVComplexDouble)); + + scale = 1.0 / (s->window_size - s->hop_size); + for (int n = 0; n < s->window_size; n++) + s->window_func_lut[n] = tx_out[0][n] * scale; + + av_tx_uninit(&tx); + av_tx_uninit(&itx); + + av_freep(&tx_in[0]); + av_freep(&tx_in[1]); + av_freep(&tx_out[0]); + av_freep(&tx_out[1]); + } av_frame_free(&s->in); av_frame_free(&s->out);