| @@ -23,8 +23,8 @@ · 22 unmodified lines |
| 23 | 23 | #include "libavfilter/internal.h" |
| 24 | 24 | #include "libavutil/common.h" |
| 25 | 25 | #include "libavutil/opt.h" |
| 26 | | −#include "libavcodec/avfft.h" |
| 27 | 26 | #include "libavutil/eval.h" |
| 27 | +#include "libavutil/tx.h" |
| 28 | 28 | #include "audio.h" |
| 29 | 29 | #include "filters.h" |
| 30 | 30 | #include "window_func.h" |
| @@ -34,11 +34,12 @@ typedef struct AFFTFiltContext { · 3 unmodified lines |
| 34 | 34 | char *real_str; |
| 35 | 35 | char *img_str; |
| 36 | 36 | int fft_size; |
| 37 | | − int fft_bits; |
| 38 | 37 | |
| 39 | | − FFTContext *fft, *ifft; |
| 40 | | − FFTComplex **fft_data; |
| 41 | | − FFTComplex **fft_temp; |
| 38 | + AVTXContext *fft, *ifft; |
| 39 | + av_tx_fn tx_fn, itx_fn; |
| 40 | + AVComplexFloat **fft_in; |
| 41 | + AVComplexFloat **fft_out; |
| 42 | + AVComplexFloat **fft_temp; |
| 42 | 43 | int nb_exprs; |
| 43 | 44 | int channels; |
| 44 | 45 | int window_size; |
| @@ -100,7 +101,7 @@ static inline double getreal(void *priv, double x, double ch) · 55 unmodified lines |
| 100 | 101 | ich = av_clip(ch, 0, s->nb_exprs - 1); |
| 101 | 102 | ix = av_clip(x, 0, s->window_size / 2); |
| 102 | 103 | |
| 103 | | − return s->fft_data[ich][ix].re; |
| 104 | + return s->fft_out[ich][ix].re; |
| 104 | 105 | } |
| 105 | 106 | |
| 106 | 107 | static inline double getimag(void *priv, double x, double ch) |
| @@ -111,7 +112,7 @@ static inline double getimag(void *priv, double x, double ch) · 4 unmodified lines |
| 111 | 112 | ich = av_clip(ch, 0, s->nb_exprs - 1); |
| 112 | 113 | ix = av_clip(x, 0, s->window_size / 2); |
| 113 | 114 | |
| 114 | | − return s->fft_data[ich][ix].im; |
| 115 | + return s->fft_out[ich][ix].im; |
| 115 | 116 | } |
| 116 | 117 | |
| 117 | 118 | static double realf(void *priv, double x, double ch) { return getreal(priv, x, ch); } |
| @@ -126,22 +127,28 @@ static int config_input(AVFilterLink *inlink) · 8 unmodified lines |
| 126 | 127 | AFFTFiltContext *s = ctx->priv; |
| 127 | 128 | char *saveptr = NULL; |
| 128 | 129 | int ret = 0, ch; |
| 129 | | − float overlap; |
| 130 | + float overlap, scale; |
| 130 | 131 | char *args; |
| 131 | 132 | const char *last_expr = "1"; |
| 132 | 133 | |
| 133 | 134 | s->channels = inlink->channels; |
| 134 | 135 | s->pts = AV_NOPTS_VALUE; |
| 135 | | − s->fft_bits = av_log2(s->fft_size); |
| 136 | | − s->fft = av_fft_init(s->fft_bits, 0); |
| 137 | | − s->ifft = av_fft_init(s->fft_bits, 1); |
| 138 | | − if (!s->fft || !s->ifft) |
| 139 | | − return AVERROR(ENOMEM); |
| 136 | + ret = av_tx_init(&s->fft, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0); |
| 137 | + if (ret < 0) |
| 138 | + return ret; |
| 139 | + |
| 140 | + ret = av_tx_init(&s->ifft, &s->itx_fn, AV_TX_FLOAT_FFT, 1, s->fft_size, &scale, 0); |
| 141 | + if (ret < 0) |
| 142 | + return ret; |
| 140 | 143 | |
| 141 | | − s->window_size = 1 << s->fft_bits; |
| 144 | + s->window_size = s->fft_size; |
| 142 | 145 | |
| 143 | | − s->fft_data = av_calloc(inlink->channels, sizeof(*s->fft_data)); |
| 144 | | − if (!s->fft_data) |
| 146 | + s->fft_in = av_calloc(inlink->channels, sizeof(*s->fft_in)); |
| 147 | + if (!s->fft_in) |
| 148 | + return AVERROR(ENOMEM); |
| 149 | + |
| 150 | + s->fft_out = av_calloc(inlink->channels, sizeof(*s->fft_out)); |
| 151 | + if (!s->fft_out) |
| 145 | 152 | return AVERROR(ENOMEM); |
| 146 | 153 | |
| 147 | 154 | s->fft_temp = av_calloc(inlink->channels, sizeof(*s->fft_temp)); |
| @@ -149,12 +156,14 @@ static int config_input(AVFilterLink *inlink) · 1 unmodified line |
| 149 | 156 | return AVERROR(ENOMEM); |
| 150 | 157 | |
| 151 | 158 | for (ch = 0; ch < inlink->channels; ch++) { |
| 152 | | − s->fft_data[ch] = av_calloc(s->window_size, sizeof(**s->fft_data)); |
| 153 | | − if (!s->fft_data[ch]) |
| 159 | + s->fft_in[ch] = av_calloc(s->window_size, sizeof(**s->fft_in)); |
| 160 | + if (!s->fft_in[ch]) |
| 161 | + return AVERROR(ENOMEM); |
| 162 | + |
| 163 | + s->fft_out[ch] = av_calloc(s->window_size, sizeof(**s->fft_out)); |
| 164 | + if (!s->fft_out[ch]) |
| 154 | 165 | return AVERROR(ENOMEM); |
| 155 | | − } |
| 156 | 166 | |
| 157 | | − for (ch = 0; ch < inlink->channels; ch++) { |
| 158 | 167 | s->fft_temp[ch] = av_calloc(s->window_size, sizeof(**s->fft_temp)); |
| 159 | 168 | if (!s->fft_temp[ch]) |
| 160 | 169 | return AVERROR(ENOMEM); |
| @@ -254,16 +263,16 @@ static int filter_frame(AVFilterLink *inlink) · 93 unmodified lines |
| 254 | 263 | |
| 255 | 264 | for (ch = 0; ch < inlink->channels; ch++) { |
| 256 | 265 | const float *src = (float *)in->extended_data[ch]; |
| 257 | | − FFTComplex *fft_data = s->fft_data[ch]; |
| 266 | + AVComplexFloat *fft_in = s->fft_in[ch]; |
| 258 | 267 | |
| 259 | 268 | for (n = 0; n < in->nb_samples; n++) { |
| 260 | | − fft_data[n].re = src[n] * s->window_func_lut[n]; |
| 261 | | − fft_data[n].im = 0; |
| 269 | + fft_in[n].re = src[n] * s->window_func_lut[n]; |
| 270 | + fft_in[n].im = 0; |
| 262 | 271 | } |
| 263 | 272 | |
| 264 | 273 | for (; n < window_size; n++) { |
| 265 | | − fft_data[n].re = 0; |
| 266 | | − fft_data[n].im = 0; |
| 274 | + fft_in[n].re = 0; |
| 275 | + fft_in[n].im = 0; |
| 267 | 276 | } |
| 268 | 277 | } |
| 269 | 278 | |
| @@ -273,15 +282,15 @@ static int filter_frame(AVFilterLink *inlink) · 3 unmodified lines |
| 273 | 282 | values[VAR_CHANNELS] = inlink->channels; |
| 274 | 283 | |
| 275 | 284 | for (ch = 0; ch < inlink->channels; ch++) { |
| 276 | | − FFTComplex *fft_data = s->fft_data[ch]; |
| 285 | + AVComplexFloat *fft_in = s->fft_in[ch]; |
| 286 | + AVComplexFloat *fft_out = s->fft_out[ch]; |
| 277 | 287 | |
| 278 | | − av_fft_permute(s->fft, fft_data); |
| 279 | | − av_fft_calc(s->fft, fft_data); |
| 288 | + s->tx_fn(s->fft, fft_out, fft_in, sizeof(float)); |
| 280 | 289 | } |
| 281 | 290 | |
| 282 | 291 | for (ch = 0; ch < inlink->channels; ch++) { |
| 283 | | − FFTComplex *fft_data = s->fft_data[ch]; |
| 284 | | − FFTComplex *fft_temp = s->fft_temp[ch]; |
| 292 | + AVComplexFloat *fft_out = s->fft_out[ch]; |
| 293 | + AVComplexFloat *fft_temp = s->fft_temp[ch]; |
| 285 | 294 | float *buf = (float *)s->buffer->extended_data[ch]; |
| 286 | 295 | int x; |
| 287 | 296 | values[VAR_CHANNEL] = ch; |
| @@ -290,8 +299,8 @@ static int filter_frame(AVFilterLink *inlink) · 2 unmodified lines |
| 290 | 299 | float fr, fi; |
| 291 | 300 | |
| 292 | 301 | values[VAR_BIN] = n; |
| 293 | | − values[VAR_REAL] = fft_data[n].re; |
| 294 | | − values[VAR_IMAG] = fft_data[n].im; |
| 302 | + values[VAR_REAL] = fft_out[n].re; |
| 303 | + values[VAR_IMAG] = fft_out[n].im; |
| 295 | 304 | |
| 296 | 305 | fr = av_expr_eval(s->real[ch], values, s); |
| 297 | 306 | fi = av_expr_eval(s->imag[ch], values, s); |
| @@ -305,11 +314,10 @@ static int filter_frame(AVFilterLink *inlink) · 7 unmodified lines |
| 305 | 314 | fft_temp[n].im = -fft_temp[x].im; |
| 306 | 315 | } |
| 307 | 316 | |
| 308 | | − av_fft_permute(s->ifft, fft_temp); |
| 309 | | − av_fft_calc(s->ifft, fft_temp); |
| 317 | + s->itx_fn(s->ifft, fft_out, fft_temp, sizeof(float)); |
| 310 | 318 | |
| 311 | 319 | for (i = 0; i < window_size; i++) { |
| 312 | | − buf[i] += s->fft_temp[ch][i].re * f; |
| 320 | + buf[i] += s->fft_out[ch][i].re * f; |
| 313 | 321 | } |
| 314 | 322 | } |
| 315 | 323 | |
| @@ -434,16 +442,19 @@ static av_cold void uninit(AVFilterContext *ctx) · 118 unmodified lines |
| 434 | 442 | AFFTFiltContext *s = ctx->priv; |
| 435 | 443 | int i; |
| 436 | 444 | |
| 437 | | − av_fft_end(s->fft); |
| 438 | | − av_fft_end(s->ifft); |
| 445 | + av_tx_uninit(&s->fft); |
| 446 | + av_tx_uninit(&s->ifft); |
| 439 | 447 | |
| 440 | 448 | for (i = 0; i < s->channels; i++) { |
| 441 | | − if (s->fft_data) |
| 442 | | − av_freep(&s->fft_data[i]); |
| 449 | + if (s->fft_in) |
| 450 | + av_freep(&s->fft_in[i]); |
| 451 | + if (s->fft_out) |
| 452 | + av_freep(&s->fft_out[i]); |
| 443 | 453 | if (s->fft_temp) |
| 444 | 454 | av_freep(&s->fft_temp[i]); |
| 445 | 455 | } |
| 446 | | − av_freep(&s->fft_data); |
| 456 | + av_freep(&s->fft_in); |
| 457 | + av_freep(&s->fft_out); |
| 447 | 458 | av_freep(&s->fft_temp); |
| 448 | 459 | |
| 449 | 460 | for (i = 0; i < s->nb_exprs; i++) { |