Showing the changes to libavfilter (1 of 2 files). Show all
Unified · Split
| @@ -23,8 +23,8 @@ · 22 unmodified lines | |||
| 23 | #include "libavfilter/internal.h" | 23 | #include "libavfilter/internal.h" |
| 24 | #include "libavutil/common.h" | 24 | #include "libavutil/common.h" |
| 25 | #include "libavutil/opt.h" | 25 | #include "libavutil/opt.h" |
| 26 | #include "libavcodec/avfft.h" | ||
| 27 | #include "libavutil/eval.h" | 26 | #include "libavutil/eval.h" |
| 27 | #include "libavutil/tx.h" | ||
| 28 | #include "audio.h" | 28 | #include "audio.h" |
| 29 | #include "filters.h" | 29 | #include "filters.h" |
| 30 | #include "window_func.h" | 30 | #include "window_func.h" |
| @@ -34,11 +34,12 @@ typedef struct AFFTFiltContext { · 3 unmodified lines | |||
| 34 | char *real_str; | 34 | char *real_str; |
| 35 | char *img_str; | 35 | char *img_str; |
| 36 | int fft_size; | 36 | int fft_size; |
| 37 | int fft_bits; | ||
| 38 | 37 | ||
| 39 | FFTContext *fft, *ifft; | 38 | AVTXContext *fft, *ifft; |
| 40 | FFTComplex **fft_data; | 39 | av_tx_fn tx_fn, itx_fn; |
| 41 | FFTComplex **fft_temp; | 40 | AVComplexFloat **fft_in; |
| 41 | AVComplexFloat **fft_out; | ||
| 42 | AVComplexFloat **fft_temp; | ||
| 42 | int nb_exprs; | 43 | int nb_exprs; |
| 43 | int channels; | 44 | int channels; |
| 44 | int window_size; | 45 | int window_size; |
| @@ -100,7 +101,7 @@ static inline double getreal(void *priv, double x, double ch) · 55 unmodified lines | |||
| 100 | ich = av_clip(ch, 0, s->nb_exprs - 1); | 101 | ich = av_clip(ch, 0, s->nb_exprs - 1); |
| 101 | ix = av_clip(x, 0, s->window_size / 2); | 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 | static inline double getimag(void *priv, double x, double ch) | 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 | ich = av_clip(ch, 0, s->nb_exprs - 1); | 112 | ich = av_clip(ch, 0, s->nb_exprs - 1); |
| 112 | ix = av_clip(x, 0, s->window_size / 2); | 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 | static double realf(void *priv, double x, double ch) { return getreal(priv, x, ch); } | 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 | AFFTFiltContext *s = ctx->priv; | 127 | AFFTFiltContext *s = ctx->priv; |
| 127 | char *saveptr = NULL; | 128 | char *saveptr = NULL; |
| 128 | int ret = 0, ch; | 129 | int ret = 0, ch; |
| 129 | float overlap; | 130 | float overlap, scale; |
| 130 | char *args; | 131 | char *args; |
| 131 | const char *last_expr = "1"; | 132 | const char *last_expr = "1"; |
| 132 | 133 | ||
| 133 | s->channels = inlink->channels; | 134 | s->channels = inlink->channels; |
| 134 | s->pts = AV_NOPTS_VALUE; | 135 | s->pts = AV_NOPTS_VALUE; |
| 135 | s->fft_bits = av_log2(s->fft_size); | 136 | ret = av_tx_init(&s->fft, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0); |
| 136 | s->fft = av_fft_init(s->fft_bits, 0); | 137 | if (ret < 0) |
| 137 | s->ifft = av_fft_init(s->fft_bits, 1); | 138 | return ret; |
| 138 | if (!s->fft || !s->ifft) | 139 | |
| 139 | return AVERROR(ENOMEM); | 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)); | 146 | s->fft_in = av_calloc(inlink->channels, sizeof(*s->fft_in)); |
| 144 | if (!s->fft_data) | 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 | return AVERROR(ENOMEM); | 152 | return AVERROR(ENOMEM); |
| 146 | 153 | ||
| 147 | s->fft_temp = av_calloc(inlink->channels, sizeof(*s->fft_temp)); | 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 | return AVERROR(ENOMEM); | 156 | return AVERROR(ENOMEM); |
| 150 | 157 | ||
| 151 | for (ch = 0; ch < inlink->channels; ch++) { | 158 | for (ch = 0; ch < inlink->channels; ch++) { |
| 152 | s->fft_data[ch] = av_calloc(s->window_size, sizeof(**s->fft_data)); | 159 | s->fft_in[ch] = av_calloc(s->window_size, sizeof(**s->fft_in)); |
| 153 | if (!s->fft_data[ch]) | 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 | return AVERROR(ENOMEM); | 165 | return AVERROR(ENOMEM); |
| 155 | } | ||
| 156 | 166 | ||
| 157 | for (ch = 0; ch < inlink->channels; ch++) { | ||
| 158 | s->fft_temp[ch] = av_calloc(s->window_size, sizeof(**s->fft_temp)); | 167 | s->fft_temp[ch] = av_calloc(s->window_size, sizeof(**s->fft_temp)); |
| 159 | if (!s->fft_temp[ch]) | 168 | if (!s->fft_temp[ch]) |
| 160 | return AVERROR(ENOMEM); | 169 | return AVERROR(ENOMEM); |
| @@ -254,16 +263,16 @@ static int filter_frame(AVFilterLink *inlink) · 93 unmodified lines | |||
| 254 | 263 | ||
| 255 | for (ch = 0; ch < inlink->channels; ch++) { | 264 | for (ch = 0; ch < inlink->channels; ch++) { |
| 256 | const float *src = (float *)in->extended_data[ch]; | 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 | for (n = 0; n < in->nb_samples; n++) { | 268 | for (n = 0; n < in->nb_samples; n++) { |
| 260 | fft_data[n].re = src[n] * s->window_func_lut[n]; | 269 | fft_in[n].re = src[n] * s->window_func_lut[n]; |
| 261 | fft_data[n].im = 0; | 270 | fft_in[n].im = 0; |
| 262 | } | 271 | } |
| 263 | 272 | ||
| 264 | for (; n < window_size; n++) { | 273 | for (; n < window_size; n++) { |
| 265 | fft_data[n].re = 0; | 274 | fft_in[n].re = 0; |
| 266 | fft_data[n].im = 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 | values[VAR_CHANNELS] = inlink->channels; | 282 | values[VAR_CHANNELS] = inlink->channels; |
| 274 | 283 | ||
| 275 | for (ch = 0; ch < inlink->channels; ch++) { | 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); | 288 | s->tx_fn(s->fft, fft_out, fft_in, sizeof(float)); |
| 279 | av_fft_calc(s->fft, fft_data); | ||
| 280 | } | 289 | } |
| 281 | 290 | ||
| 282 | for (ch = 0; ch < inlink->channels; ch++) { | 291 | for (ch = 0; ch < inlink->channels; ch++) { |
| 283 | FFTComplex *fft_data = s->fft_data[ch]; | 292 | AVComplexFloat *fft_out = s->fft_out[ch]; |
| 284 | FFTComplex *fft_temp = s->fft_temp[ch]; | 293 | AVComplexFloat *fft_temp = s->fft_temp[ch]; |
| 285 | float *buf = (float *)s->buffer->extended_data[ch]; | 294 | float *buf = (float *)s->buffer->extended_data[ch]; |
| 286 | int x; | 295 | int x; |
| 287 | values[VAR_CHANNEL] = ch; | 296 | values[VAR_CHANNEL] = ch; |
| @@ -290,8 +299,8 @@ static int filter_frame(AVFilterLink *inlink) · 2 unmodified lines | |||
| 290 | float fr, fi; | 299 | float fr, fi; |
| 291 | 300 | ||
| 292 | values[VAR_BIN] = n; | 301 | values[VAR_BIN] = n; |
| 293 | values[VAR_REAL] = fft_data[n].re; | 302 | values[VAR_REAL] = fft_out[n].re; |
| 294 | values[VAR_IMAG] = fft_data[n].im; | 303 | values[VAR_IMAG] = fft_out[n].im; |
| 295 | 304 | ||
| 296 | fr = av_expr_eval(s->real[ch], values, s); | 305 | fr = av_expr_eval(s->real[ch], values, s); |
| 297 | fi = av_expr_eval(s->imag[ch], values, s); | 306 | fi = av_expr_eval(s->imag[ch], values, s); |
| @@ -305,11 +314,10 @@ static int filter_frame(AVFilterLink *inlink) · 7 unmodified lines | |||
| 305 | fft_temp[n].im = -fft_temp[x].im; | 314 | fft_temp[n].im = -fft_temp[x].im; |
| 306 | } | 315 | } |
| 307 | 316 | ||
| 308 | av_fft_permute(s->ifft, fft_temp); | 317 | s->itx_fn(s->ifft, fft_out, fft_temp, sizeof(float)); |
| 309 | av_fft_calc(s->ifft, fft_temp); | ||
| 310 | 318 | ||
| 311 | for (i = 0; i < window_size; i++) { | 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 | AFFTFiltContext *s = ctx->priv; | 442 | AFFTFiltContext *s = ctx->priv; |
| 435 | int i; | 443 | int i; |
| 436 | 444 | ||
| 437 | av_fft_end(s->fft); | 445 | av_tx_uninit(&s->fft); |
| 438 | av_fft_end(s->ifft); | 446 | av_tx_uninit(&s->ifft); |
| 439 | 447 | ||
| 440 | for (i = 0; i < s->channels; i++) { | 448 | for (i = 0; i < s->channels; i++) { |
| 441 | if (s->fft_data) | 449 | if (s->fft_in) |
| 442 | av_freep(&s->fft_data[i]); | 450 | av_freep(&s->fft_in[i]); |
| 451 | if (s->fft_out) | ||
| 452 | av_freep(&s->fft_out[i]); | ||
| 443 | if (s->fft_temp) | 453 | if (s->fft_temp) |
| 444 | av_freep(&s->fft_temp[i]); | 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 | av_freep(&s->fft_temp); | 458 | av_freep(&s->fft_temp); |
| 448 | 459 | ||
| 449 | for (i = 0; i < s->nb_exprs; i++) { | 460 | for (i = 0; i < s->nb_exprs; i++) { |