|
|
|
@ -25,6 +25,10 @@ |
|
|
|
|
|
|
|
|
|
#include "config.h" |
|
|
|
|
|
|
|
|
|
#ifndef AVFFT |
|
|
|
|
#define AVFFT 0 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include <math.h> |
|
|
|
|
#if HAVE_UNISTD_H |
|
|
|
|
#include <unistd.h> |
|
|
|
@ -39,7 +43,12 @@ |
|
|
|
|
#include "libavutil/mathematics.h" |
|
|
|
|
#include "libavutil/time.h" |
|
|
|
|
|
|
|
|
|
#if AVFFT |
|
|
|
|
#include "libavcodec/avfft.h" |
|
|
|
|
#else |
|
|
|
|
#include "libavcodec/fft.h" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
#include "libavcodec/dct.h" |
|
|
|
|
#include "libavcodec/rdft.h" |
|
|
|
@ -55,7 +64,7 @@ |
|
|
|
|
pim += (MUL16(are, bim) + MUL16(bre, aim)); \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
#if FFT_FLOAT || AVFFT |
|
|
|
|
#define RANGE 1.0 |
|
|
|
|
#define REF_SCALE(x, bits) (x) |
|
|
|
|
#define FMT "%10.6f" |
|
|
|
@ -211,6 +220,134 @@ static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale) |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void fft_init(FFTContext **s, int nbits, int inverse) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
*s = av_fft_init(nbits, inverse); |
|
|
|
|
#else |
|
|
|
|
ff_fft_init(*s, nbits, inverse); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void mdct_init(FFTContext **s, int nbits, int inverse, double scale) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
*s = av_mdct_init(nbits, inverse, scale); |
|
|
|
|
#else |
|
|
|
|
ff_mdct_init(*s, nbits, inverse, scale); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_mdct_calc(s, output, input); |
|
|
|
|
#else |
|
|
|
|
s->mdct_calc(s, output, input); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void imdct_calc(struct FFTContext *s, FFTSample *output, const FFTSample *input) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_imdct_calc(s, output, input); |
|
|
|
|
#else |
|
|
|
|
s->imdct_calc(s, output, input); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void fft_permute(FFTContext *s, FFTComplex *z) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_fft_permute(s, z); |
|
|
|
|
#else |
|
|
|
|
s->fft_permute(s, z); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void fft_calc(FFTContext *s, FFTComplex *z) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_fft_calc(s, z); |
|
|
|
|
#else |
|
|
|
|
s->fft_calc(s, z); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void mdct_end(FFTContext *s) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_mdct_end(s); |
|
|
|
|
#else |
|
|
|
|
ff_mdct_end(s); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void fft_end(FFTContext *s) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_fft_end(s); |
|
|
|
|
#else |
|
|
|
|
ff_fft_end(s); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
static inline void rdft_init(RDFTContext **r, int nbits, enum RDFTransformType trans) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
*r = av_rdft_init(nbits, trans); |
|
|
|
|
#else |
|
|
|
|
ff_rdft_init(*r, nbits, trans); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void dct_init(DCTContext **d, int nbits, enum DCTTransformType trans) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
*d = av_dct_init(nbits, trans); |
|
|
|
|
#else |
|
|
|
|
ff_dct_init(*d, nbits, trans); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void rdft_calc(RDFTContext *r, FFTSample *tab) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_rdft_calc(r, tab); |
|
|
|
|
#else |
|
|
|
|
r->rdft_calc(r, tab); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void dct_calc(DCTContext *d, FFTSample *data) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_dct_calc(d, data); |
|
|
|
|
#else |
|
|
|
|
d->dct_calc(d, data); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void rdft_end(RDFTContext *r) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_rdft_end(r); |
|
|
|
|
#else |
|
|
|
|
ff_rdft_end(r); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void dct_end(DCTContext *d) |
|
|
|
|
{ |
|
|
|
|
#if AVFFT |
|
|
|
|
av_dct_end(d); |
|
|
|
|
#else |
|
|
|
|
ff_dct_end(d); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
#endif /* FFT_FLOAT */ |
|
|
|
|
|
|
|
|
|
static void help(void) |
|
|
|
|
{ |
|
|
|
|
av_log(NULL, AV_LOG_INFO, |
|
|
|
@ -241,10 +378,10 @@ int main(int argc, char **argv) |
|
|
|
|
FFTComplex *tab, *tab1, *tab_ref; |
|
|
|
|
FFTSample *tab2; |
|
|
|
|
enum tf_transform transform = TRANSFORM_FFT; |
|
|
|
|
FFTContext m, s; |
|
|
|
|
FFTContext *m, *s; |
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
RDFTContext r; |
|
|
|
|
DCTContext d; |
|
|
|
|
RDFTContext *r; |
|
|
|
|
DCTContext *d; |
|
|
|
|
#endif /* FFT_FLOAT */ |
|
|
|
|
int it, i, err = 1; |
|
|
|
|
int do_speed = 0, do_inverse = 0; |
|
|
|
@ -252,6 +389,16 @@ int main(int argc, char **argv) |
|
|
|
|
double scale = 1.0; |
|
|
|
|
AVLFG prng; |
|
|
|
|
|
|
|
|
|
#if !AVFFT |
|
|
|
|
s = av_mallocz(sizeof(*s)); |
|
|
|
|
m = av_mallocz(sizeof(*m)); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if !AVFFT && FFT_FLOAT |
|
|
|
|
r = av_mallocz(sizeof(*r)); |
|
|
|
|
d = av_mallocz(sizeof(*d)); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
av_lfg_init(&prng, 1); |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
@ -313,7 +460,7 @@ int main(int argc, char **argv) |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "IMDCT"); |
|
|
|
|
else |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "MDCT"); |
|
|
|
|
ff_mdct_init(&m, fft_nbits, do_inverse, scale); |
|
|
|
|
mdct_init(&m, fft_nbits, do_inverse, scale); |
|
|
|
|
break; |
|
|
|
|
#endif /* CONFIG_MDCT */ |
|
|
|
|
case TRANSFORM_FFT: |
|
|
|
@ -321,7 +468,7 @@ int main(int argc, char **argv) |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "IFFT"); |
|
|
|
|
else |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "FFT"); |
|
|
|
|
ff_fft_init(&s, fft_nbits, do_inverse); |
|
|
|
|
fft_init(&s, fft_nbits, do_inverse); |
|
|
|
|
if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) |
|
|
|
|
goto cleanup; |
|
|
|
|
break; |
|
|
|
@ -332,7 +479,7 @@ int main(int argc, char **argv) |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "IDFT_C2R"); |
|
|
|
|
else |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "DFT_R2C"); |
|
|
|
|
ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); |
|
|
|
|
rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); |
|
|
|
|
if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) |
|
|
|
|
goto cleanup; |
|
|
|
|
break; |
|
|
|
@ -343,7 +490,7 @@ int main(int argc, char **argv) |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "DCT_III"); |
|
|
|
|
else |
|
|
|
|
av_log(NULL, AV_LOG_INFO, "DCT_II"); |
|
|
|
|
ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); |
|
|
|
|
dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); |
|
|
|
|
break; |
|
|
|
|
# endif /* CONFIG_DCT */ |
|
|
|
|
#endif /* FFT_FLOAT */ |
|
|
|
@ -368,19 +515,19 @@ int main(int argc, char **argv) |
|
|
|
|
case TRANSFORM_MDCT: |
|
|
|
|
if (do_inverse) { |
|
|
|
|
imdct_ref(&tab_ref->re, &tab1->re, fft_nbits); |
|
|
|
|
m.imdct_calc(&m, tab2, &tab1->re); |
|
|
|
|
imdct_calc(m, tab2, &tab1->re); |
|
|
|
|
err = check_diff(&tab_ref->re, tab2, fft_size, scale); |
|
|
|
|
} else { |
|
|
|
|
mdct_ref(&tab_ref->re, &tab1->re, fft_nbits); |
|
|
|
|
m.mdct_calc(&m, tab2, &tab1->re); |
|
|
|
|
mdct_calc(m, tab2, &tab1->re); |
|
|
|
|
err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
#endif /* CONFIG_MDCT */ |
|
|
|
|
case TRANSFORM_FFT: |
|
|
|
|
memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); |
|
|
|
|
s.fft_permute(&s, tab); |
|
|
|
|
s.fft_calc(&s, tab); |
|
|
|
|
fft_permute(s, tab); |
|
|
|
|
fft_calc(s, tab); |
|
|
|
|
|
|
|
|
|
fft_ref(tab_ref, tab1, fft_nbits); |
|
|
|
|
err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); |
|
|
|
@ -401,7 +548,7 @@ int main(int argc, char **argv) |
|
|
|
|
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
|
|
|
|
tab2[1] = tab1[fft_size_2].re; |
|
|
|
|
|
|
|
|
|
r.rdft_calc(&r, tab2); |
|
|
|
|
rdft_calc(r, tab2); |
|
|
|
|
fft_ref(tab_ref, tab1, fft_nbits); |
|
|
|
|
for (i = 0; i < fft_size; i++) { |
|
|
|
|
tab[i].re = tab2[i]; |
|
|
|
@ -413,7 +560,7 @@ int main(int argc, char **argv) |
|
|
|
|
tab2[i] = tab1[i].re; |
|
|
|
|
tab1[i].im = 0; |
|
|
|
|
} |
|
|
|
|
r.rdft_calc(&r, tab2); |
|
|
|
|
rdft_calc(r, tab2); |
|
|
|
|
fft_ref(tab_ref, tab1, fft_nbits); |
|
|
|
|
tab_ref[0].im = tab_ref[fft_size_2].re; |
|
|
|
|
err = check_diff(&tab_ref->re, tab2, fft_size, 1.0); |
|
|
|
@ -424,7 +571,7 @@ int main(int argc, char **argv) |
|
|
|
|
#if CONFIG_DCT |
|
|
|
|
case TRANSFORM_DCT: |
|
|
|
|
memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); |
|
|
|
|
d.dct_calc(&d, &tab->re); |
|
|
|
|
dct_calc(d, &tab->re); |
|
|
|
|
if (do_inverse) |
|
|
|
|
idct_ref(&tab_ref->re, &tab1->re, fft_nbits); |
|
|
|
|
else |
|
|
|
@ -450,22 +597,22 @@ int main(int argc, char **argv) |
|
|
|
|
switch (transform) { |
|
|
|
|
case TRANSFORM_MDCT: |
|
|
|
|
if (do_inverse) |
|
|
|
|
m.imdct_calc(&m, &tab->re, &tab1->re); |
|
|
|
|
imdct_calc(m, &tab->re, &tab1->re); |
|
|
|
|
else |
|
|
|
|
m.mdct_calc(&m, &tab->re, &tab1->re); |
|
|
|
|
mdct_calc(m, &tab->re, &tab1->re); |
|
|
|
|
break; |
|
|
|
|
case TRANSFORM_FFT: |
|
|
|
|
memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); |
|
|
|
|
s.fft_calc(&s, tab); |
|
|
|
|
fft_calc(s, tab); |
|
|
|
|
break; |
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
case TRANSFORM_RDFT: |
|
|
|
|
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
|
|
|
|
r.rdft_calc(&r, tab2); |
|
|
|
|
rdft_calc(r, tab2); |
|
|
|
|
break; |
|
|
|
|
case TRANSFORM_DCT: |
|
|
|
|
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
|
|
|
|
d.dct_calc(&d, tab2); |
|
|
|
|
dct_calc(d, tab2); |
|
|
|
|
break; |
|
|
|
|
#endif /* FFT_FLOAT */ |
|
|
|
|
} |
|
|
|
@ -485,21 +632,21 @@ int main(int argc, char **argv) |
|
|
|
|
switch (transform) { |
|
|
|
|
#if CONFIG_MDCT |
|
|
|
|
case TRANSFORM_MDCT: |
|
|
|
|
ff_mdct_end(&m); |
|
|
|
|
mdct_end(m); |
|
|
|
|
break; |
|
|
|
|
#endif /* CONFIG_MDCT */ |
|
|
|
|
case TRANSFORM_FFT: |
|
|
|
|
ff_fft_end(&s); |
|
|
|
|
fft_end(s); |
|
|
|
|
break; |
|
|
|
|
#if FFT_FLOAT |
|
|
|
|
# if CONFIG_RDFT |
|
|
|
|
case TRANSFORM_RDFT: |
|
|
|
|
ff_rdft_end(&r); |
|
|
|
|
rdft_end(r); |
|
|
|
|
break; |
|
|
|
|
# endif /* CONFIG_RDFT */ |
|
|
|
|
# if CONFIG_DCT |
|
|
|
|
case TRANSFORM_DCT: |
|
|
|
|
ff_dct_end(&d); |
|
|
|
|
dct_end(d); |
|
|
|
|
break; |
|
|
|
|
# endif /* CONFIG_DCT */ |
|
|
|
|
#endif /* FFT_FLOAT */ |
|
|
|
@ -512,6 +659,16 @@ cleanup: |
|
|
|
|
av_free(tab_ref); |
|
|
|
|
av_free(exptab); |
|
|
|
|
|
|
|
|
|
#if !AVFFT |
|
|
|
|
av_free(s); |
|
|
|
|
av_free(m); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if !AVFFT && FFT_FLOAT |
|
|
|
|
av_free(r); |
|
|
|
|
av_free(d); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (err) |
|
|
|
|
printf("Error: %d.\n", err); |
|
|
|
|
|
|
|
|
|