History

avfilter/af_atempo: switch to rdft from lavu/tx

Paul B Mahol committed 4 years ago

Commit 800dfd21 parent e8f43962 files · +64 −65Browse files

Unified · Split

2 files
  1. configure +0 −3
  2. libavfilter/af_atempo.c +64 −62
configure+0−3
@@ -3610,8 +3610,6 @@ amovie_filter_deps="avcodec avformat" · 3609 unmodified lines
36103610 aresample_filter_deps="swresample"
36113611 asr_filter_deps="pocketsphinx"
36123612 ass_filter_deps="libass"
3613−atempo_filter_deps="avcodec"
3614−atempo_filter_select="rdft"
36153613 avgblur_opencl_filter_deps="opencl"
36163614 avgblur_vulkan_filter_deps="vulkan spirv_compiler"
36173615 azmq_filter_deps="libzmq"
@@ -7386,7 +7384,6 @@ enabled zlib && add_cppflags -DZLIB_CONST · 3768 unmodified lines
73867384 # conditional library dependencies, in any order
73877385 enabled amovie_filter && prepend avfilter_deps "avformat avcodec"
73887386 enabled aresample_filter && prepend avfilter_deps "swresample"
7389−enabled atempo_filter && prepend avfilter_deps "avcodec"
73907387 enabled bm3d_filter && prepend avfilter_deps "avcodec"
73917388 enabled cover_rect_filter && prepend avfilter_deps "avformat avcodec"
73927389 enabled ebur128_filter && enabled swresample && prepend avfilter_deps "swresample"
libavfilter/af_atempo.c+64−62
@@ -39,13 +39,13 @@ · 38 unmodified lines
3939 */
4040
4141 #include <float.h>
42−#include "libavcodec/avfft.h"
4342 #include "libavutil/avassert.h"
4443 #include "libavutil/avstring.h"
4544 #include "libavutil/channel_layout.h"
4645 #include "libavutil/eval.h"
4746 #include "libavutil/opt.h"
4847 #include "libavutil/samplefmt.h"
48+#include "libavutil/tx.h"
4949 #include "avfilter.h"
5050 #include "audio.h"
5151 #include "internal.h"
@@ -67,7 +67,8 @@ typedef struct AudioFragment { · 15 unmodified lines
6767
6868 // rDFT transform of the down-mixed mono fragment, used for
6969 // fast waveform alignment via correlation in frequency domain:
70− FFTSample *xdat;
70+ float *xdat_in;
71+ float *xdat;
7172 } AudioFragment;
7273
7374 /**
@@ -140,9 +141,11 @@ typedef struct ATempoContext { · 66 unmodified lines
140141 FilterState state;
141142
142143 // for fast correlation calculation in frequency domain:
143− RDFTContext *real_to_complex;
144− RDFTContext *complex_to_real;
145− FFTSample *correlation;
144+ AVTXContext *real_to_complex;
145+ AVTXContext *complex_to_real;
146+ av_tx_fn r2c_fn, c2r_fn;
147+ float *correlation_in;
148+ float *correlation;
146149
147150 // for managing AVFilterPad.request_frame and AVFilterPad.filter_frame
148151 AVFrame *dst_buffer;
@@ -228,18 +231,18 @@ static void yae_release_buffers(ATempoContext *atempo) · 79 unmodified lines
228231
229232 av_freep(&atempo->frag[0].data);
230233 av_freep(&atempo->frag[1].data);
234+ av_freep(&atempo->frag[0].xdat_in);
235+ av_freep(&atempo->frag[1].xdat_in);
231236 av_freep(&atempo->frag[0].xdat);
232237 av_freep(&atempo->frag[1].xdat);
233238
234239 av_freep(&atempo->buffer);
235240 av_freep(&atempo->hann);
241+ av_freep(&atempo->correlation_in);
236242 av_freep(&atempo->correlation);
237243
238− av_rdft_end(atempo->real_to_complex);
239− atempo->real_to_complex = NULL;
240−
241− av_rdft_end(atempo->complex_to_real);
242− atempo->complex_to_real = NULL;
244+ av_tx_uninit(&atempo->real_to_complex);
245+ av_tx_uninit(&atempo->complex_to_real);
243246 }
244247
245248 /* av_realloc is not aligned enough; fortunately, the data does not need to
@@ -247,7 +250,7 @@ static void yae_release_buffers(ATempoContext *atempo) · 1 unmodified line
247250 #define RE_MALLOC_OR_FAIL(field, field_size) \
248251 do { \
249252 av_freep(&field); \
250− field = av_malloc(field_size); \
253+ field = av_calloc(field_size, 1); \
251254 if (!field) { \
252255 yae_release_buffers(atempo); \
253256 return AVERROR(ENOMEM); \
@@ -265,6 +268,7 @@ static int yae_reset(ATempoContext *atempo, · 11 unmodified lines
265268 {
266269 const int sample_size = av_get_bytes_per_sample(format);
267270 uint32_t nlevels = 0;
271+ float scale = 1.f, iscale = 1.f;
268272 uint32_t pot;
269273 int i;
270274
@@ -288,29 +292,29 @@ static int yae_reset(ATempoContext *atempo, · 17 unmodified lines
288292 // initialize audio fragment buffers:
289293 RE_MALLOC_OR_FAIL(atempo->frag[0].data, atempo->window * atempo->stride);
290294 RE_MALLOC_OR_FAIL(atempo->frag[1].data, atempo->window * atempo->stride);
291− RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, atempo->window * sizeof(FFTComplex));
292− RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, atempo->window * sizeof(FFTComplex));
295+ RE_MALLOC_OR_FAIL(atempo->frag[0].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat));
296+ RE_MALLOC_OR_FAIL(atempo->frag[1].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat));
297+ RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, (atempo->window + 1) * sizeof(AVComplexFloat));
298+ RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, (atempo->window + 1) * sizeof(AVComplexFloat));
293299
294300 // initialize rDFT contexts:
295− av_rdft_end(atempo->real_to_complex);
296− atempo->real_to_complex = NULL;
297−
298− av_rdft_end(atempo->complex_to_real);
299− atempo->complex_to_real = NULL;
301+ av_tx_uninit(&atempo->real_to_complex);
302+ av_tx_uninit(&atempo->complex_to_real);
300303
301− atempo->real_to_complex = av_rdft_init(nlevels + 1, DFT_R2C);
304+ av_tx_init(&atempo->real_to_complex, &atempo->r2c_fn, AV_TX_FLOAT_RDFT, 0, 1 << (nlevels + 1), &scale, 0);
302305 if (!atempo->real_to_complex) {
303306 yae_release_buffers(atempo);
304307 return AVERROR(ENOMEM);
305308 }
306309
307− atempo->complex_to_real = av_rdft_init(nlevels + 1, IDFT_C2R);
310+ av_tx_init(&atempo->complex_to_real, &atempo->c2r_fn, AV_TX_FLOAT_RDFT, 1, 1 << (nlevels + 1), &iscale, 0);
308311 if (!atempo->complex_to_real) {
309312 yae_release_buffers(atempo);
310313 return AVERROR(ENOMEM);
311314 }
312315
313− RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(FFTComplex));
316+ RE_MALLOC_OR_FAIL(atempo->correlation_in, (atempo->window + 1) * sizeof(AVComplexFloat));
317+ RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(AVComplexFloat));
314318
315319 atempo->ring = atempo->window * 3;
316320 RE_MALLOC_OR_FAIL(atempo->buffer, atempo->ring * atempo->stride);
@@ -348,7 +352,7 @@ static int yae_update(AVFilterContext *ctx) · 31 unmodified lines
348352 const uint8_t *src_end = src + \
349353 frag->nsamples * atempo->channels * sizeof(scalar_type); \
350354 \
351− FFTSample *xdat = frag->xdat; \
355+ float *xdat = frag->xdat_in; \
352356 scalar_type tmp; \
353357 \
354358 if (atempo->channels == 1) { \
@@ -356,27 +360,27 @@ static int yae_update(AVFilterContext *ctx) · 1 unmodified line
356360 tmp = *(const scalar_type *)src; \
357361 src += sizeof(scalar_type); \
358362 \
359− *xdat = (FFTSample)tmp; \
363+ *xdat = (float)tmp; \
360364 } \
361365 } else { \
362− FFTSample s, max, ti, si; \
366+ float s, max, ti, si; \
363367 int i; \
364368 \
365369 for (; src < src_end; xdat++) { \
366370 tmp = *(const scalar_type *)src; \
367371 src += sizeof(scalar_type); \
368372 \
369− max = (FFTSample)tmp; \
370− s = FFMIN((FFTSample)scalar_max, \
371− (FFTSample)fabsf(max)); \
373+ max = (float)tmp; \
374+ s = FFMIN((float)scalar_max, \
375+ (float)fabsf(max)); \
372376 \
373377 for (i = 1; i < atempo->channels; i++) { \
374378 tmp = *(const scalar_type *)src; \
375379 src += sizeof(scalar_type); \
376380 \
377− ti = (FFTSample)tmp; \
378− si = FFMIN((FFTSample)scalar_max, \
379− (FFTSample)fabsf(ti)); \
381+ ti = (float)tmp; \
382+ si = FFMIN((float)scalar_max, \
383+ (float)fabsf(ti)); \
380384 \
381385 if (s < si) { \
382386 s = si; \
@@ -399,7 +403,7 @@ static void yae_downmix(ATempoContext *atempo, AudioFragment *frag) · 16 unmodified lines
399403 const uint8_t *src = frag->data;
400404
401405 // init complex data buffer used for FFT and Correlation:
402− memset(frag->xdat, 0, sizeof(FFTComplex) * atempo->window);
406+ memset(frag->xdat_in, 0, sizeof(AVComplexFloat) * (atempo->window + 1));
403407
404408 if (atempo->format == AV_SAMPLE_FMT_U8) {
405409 yae_init_xdat(uint8_t, 127);
@@ -598,32 +602,24 @@ static void yae_advance_to_next_frag(ATempoContext *atempo) · 192 unmodified lines
598602 * Multiply two vectors of complex numbers (result of real_to_complex rDFT)
599603 * and transform back via complex_to_real rDFT.
600604 */
601−static void yae_xcorr_via_rdft(FFTSample *xcorr,
602− RDFTContext *complex_to_real,
603− const FFTComplex *xa,
604− const FFTComplex *xb,
605+static void yae_xcorr_via_rdft(float *xcorr_in,
606+ float *xcorr,
607+ AVTXContext *complex_to_real,
608+ av_tx_fn c2r_fn,
609+ const AVComplexFloat *xa,
610+ const AVComplexFloat *xb,
605611 const int window)
606612 {
607− FFTComplex *xc = (FFTComplex *)xcorr;
613+ AVComplexFloat *xc = (AVComplexFloat *)xcorr_in;
608614 int i;
609615
610− // NOTE: first element requires special care -- Given Y = rDFT(X),
611− // Im(Y[0]) and Im(Y[N/2]) are always zero, therefore av_rdft_calc
612− // stores Re(Y[N/2]) in place of Im(Y[0]).
613−
614− xc->re = xa->re * xb->re;
615− xc->im = xa->im * xb->im;
616− xa++;
617− xb++;
618− xc++;
619−
620− for (i = 1; i < window; i++, xa++, xb++, xc++) {
616+ for (i = 0; i <= window; i++, xa++, xb++, xc++) {
621617 xc->re = (xa->re * xb->re + xa->im * xb->im);
622618 xc->im = (xa->im * xb->re - xa->re * xb->im);
623619 }
624620
625621 // apply inverse rDFT:
626− av_rdft_calc(complex_to_real, xcorr);
622+ c2r_fn(complex_to_real, xcorr, xcorr_in, sizeof(float));
627623 }
628624
629625 /**
@@ -637,21 +633,25 @@ static int yae_align(AudioFragment *frag, · 7 unmodified lines
637633 const int window,
638634 const int delta_max,
639635 const int drift,
640− FFTSample *correlation,
641− RDFTContext *complex_to_real)
636+ float *correlation_in,
637+ float *correlation,
638+ AVTXContext *complex_to_real,
639+ av_tx_fn c2r_fn)
642640 {
643641 int best_offset = -drift;
644− FFTSample best_metric = -FLT_MAX;
645− FFTSample *xcorr;
642+ float best_metric = -FLT_MAX;
643+ float *xcorr;
646644
647645 int i0;
648646 int i1;
649647 int i;
650648
651− yae_xcorr_via_rdft(correlation,
649+ yae_xcorr_via_rdft(correlation_in,
650+ correlation,
652651 complex_to_real,
653− (const FFTComplex *)prev->xdat,
654− (const FFTComplex *)frag->xdat,
652+ c2r_fn,
653+ (const AVComplexFloat *)prev->xdat,
654+ (const AVComplexFloat *)frag->xdat,
655655 window);
656656
657657 // identify search window boundaries:
@@ -665,11 +665,11 @@ static int yae_align(AudioFragment *frag, · 7 unmodified lines
665665 xcorr = correlation + i0;
666666
667667 for (i = i0; i < i1; i++, xcorr++) {
668− FFTSample metric = *xcorr;
668+ float metric = *xcorr;
669669
670670 // normalize:
671− FFTSample drifti = (FFTSample)(drift + i);
672− metric *= drifti * (FFTSample)(i - i0) * (FFTSample)(i1 - i);
671+ float drifti = (float)(drift + i);
672+ metric *= drifti * (float)(i - i0) * (float)(i1 - i);
673673
674674 if (metric > best_metric) {
675675 best_metric = metric;
@@ -706,8 +706,10 @@ static int yae_adjust_position(ATempoContext *atempo) · 30 unmodified lines
706706 atempo->window,
707707 delta_max,
708708 drift,
709+ atempo->correlation_in,
709710 atempo->correlation,
710− atempo->complex_to_real);
711+ atempo->complex_to_real,
712+ atempo->c2r_fn);
711713
712714 if (correction) {
713715 // adjust fragment position:
@@ -833,7 +835,7 @@ yae_apply(ATempoContext *atempo, · 119 unmodified lines
833835 yae_downmix(atempo, yae_curr_frag(atempo));
834836
835837 // apply rDFT:
836− av_rdft_calc(atempo->real_to_complex, yae_curr_frag(atempo)->xdat);
838+ atempo->r2c_fn(atempo->real_to_complex, yae_curr_frag(atempo)->xdat, yae_curr_frag(atempo)->xdat_in, sizeof(float));
837839
838840 // must load the second fragment before alignment can start:
839841 if (!atempo->nfrag) {
@@ -865,7 +867,7 @@ yae_apply(ATempoContext *atempo, · 25 unmodified lines
865867 yae_downmix(atempo, yae_curr_frag(atempo));
866868
867869 // apply rDFT:
868− av_rdft_calc(atempo->real_to_complex, yae_curr_frag(atempo)->xdat);
870+ atempo->r2c_fn(atempo->real_to_complex, yae_curr_frag(atempo)->xdat, yae_curr_frag(atempo)->xdat_in, sizeof(float));
869871
870872 atempo->state = YAE_OUTPUT_OVERLAP_ADD;
871873 }
@@ -929,7 +931,7 @@ static int yae_flush(ATempoContext *atempo, · 57 unmodified lines
929931 yae_downmix(atempo, frag);
930932
931933 // apply rDFT:
932− av_rdft_calc(atempo->real_to_complex, frag->xdat);
934+ atempo->r2c_fn(atempo->real_to_complex, frag->xdat, frag->xdat_in, sizeof(float));
933935
934936 // align current fragment to previous fragment:
935937 if (yae_adjust_position(atempo)) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t