annotate rdft.c @ 10402:06bdadf410a9 libavcodec

Do not initialize ff_cos_* tables again in rdft_init, they are already initialized by ff_fft_init and using different code can result in slightly different values, in addition it crashes when the tables are hardcoded. On amd64 this slightly changes qdm2 output.
author reimar
date Thu, 15 Oct 2009 11:50:32 +0000
parents 9855215d1b2f
children 57acce8b1380
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
1 /*
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
2 * (I)RDFT transforms
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
3 * Copyright (c) 2009 Alex Converse <alex dot converse at gmail dot com>
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
4 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
5 * This file is part of FFmpeg.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
6 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
11 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
15 * Lesser General Public License for more details.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
16 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
20 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
21 #include <math.h>
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
22 #include "dsputil.h"
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
23
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
24 /**
8718
e9d9d946f213 Use full internal pathname in doxygen @file directives.
diego
parents: 8694
diff changeset
25 * @file libavcodec/rdft.c
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
26 * (Inverse) Real Discrete Fourier Transforms.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
27 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
28
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
29 /* sin(2*pi*x/n) for 0<=x<n/4, followed by n/2<=x<3n/4 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
30 DECLARE_ALIGNED_16(FFTSample, ff_sin_16[8]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
31 DECLARE_ALIGNED_16(FFTSample, ff_sin_32[16]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
32 DECLARE_ALIGNED_16(FFTSample, ff_sin_64[32]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
33 DECLARE_ALIGNED_16(FFTSample, ff_sin_128[64]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
34 DECLARE_ALIGNED_16(FFTSample, ff_sin_256[128]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
35 DECLARE_ALIGNED_16(FFTSample, ff_sin_512[256]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
36 DECLARE_ALIGNED_16(FFTSample, ff_sin_1024[512]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
37 DECLARE_ALIGNED_16(FFTSample, ff_sin_2048[1024]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
38 DECLARE_ALIGNED_16(FFTSample, ff_sin_4096[2048]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
39 DECLARE_ALIGNED_16(FFTSample, ff_sin_8192[4096]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
40 DECLARE_ALIGNED_16(FFTSample, ff_sin_16384[8192]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
41 DECLARE_ALIGNED_16(FFTSample, ff_sin_32768[16384]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
42 DECLARE_ALIGNED_16(FFTSample, ff_sin_65536[32768]);
10142
9855215d1b2f The pointers in ff_sin_tabs themselves are constant, so mark them accordingly.
reimar
parents: 8718
diff changeset
43 FFTSample * const ff_sin_tabs[] = {
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
44 ff_sin_16, ff_sin_32, ff_sin_64, ff_sin_128, ff_sin_256, ff_sin_512, ff_sin_1024,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
45 ff_sin_2048, ff_sin_4096, ff_sin_8192, ff_sin_16384, ff_sin_32768, ff_sin_65536,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
46 };
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
47
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
48 av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
49 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
50 int n = 1 << nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
51 int i;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
52 const double theta = (trans == RDFT || trans == IRIDFT ? -1 : 1)*2*M_PI/n;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
53
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
54 s->nbits = nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
55 s->inverse = trans == IRDFT || trans == IRIDFT;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
56 s->sign_convention = trans == RIDFT || trans == IRIDFT ? 1 : -1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
57
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
58 if (nbits < 4 || nbits > 16)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
59 return -1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
60
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
61 if (ff_fft_init(&s->fft, nbits-1, trans == IRDFT || trans == RIDFT) < 0)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
62 return -1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
63
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
64 s->tcos = ff_cos_tabs[nbits-4];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
65 s->tsin = ff_sin_tabs[nbits-4]+(trans == RDFT || trans == IRIDFT)*(n>>2);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
66 for (i = 0; i < (n>>2); i++) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
67 s->tsin[i] = sin(i*theta);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
68 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
69 return 0;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
70 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
71
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
72 /** Map one real FFT into two parallel real even and odd FFTs. Then interleave
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
73 * the two real FFTs into one complex FFT. Unmangle the results.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
74 * ref: http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
75 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
76 void ff_rdft_calc_c(RDFTContext* s, FFTSample* data)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
77 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
78 int i, i1, i2;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
79 FFTComplex ev, od;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
80 const int n = 1 << s->nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
81 const float k1 = 0.5;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
82 const float k2 = 0.5 - s->inverse;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
83 const FFTSample *tcos = s->tcos;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
84 const FFTSample *tsin = s->tsin;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
85
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
86 if (!s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
87 ff_fft_permute(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
88 ff_fft_calc(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
89 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
90 /* i=0 is a special case because of packing, the DC term is real, so we
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
91 are going to throw the N/2 term (also real) in with it. */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
92 ev.re = data[0];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
93 data[0] = ev.re+data[1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
94 data[1] = ev.re-data[1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
95 for (i = 1; i < (n>>2); i++) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
96 i1 = 2*i;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
97 i2 = n-i1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
98 /* Separate even and odd FFTs */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
99 ev.re = k1*(data[i1 ]+data[i2 ]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
100 od.im = -k2*(data[i1 ]-data[i2 ]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
101 ev.im = k1*(data[i1+1]-data[i2+1]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
102 od.re = k2*(data[i1+1]+data[i2+1]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
103 /* Apply twiddle factors to the odd FFT and add to the even FFT */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
104 data[i1 ] = ev.re + od.re*tcos[i] - od.im*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
105 data[i1+1] = ev.im + od.im*tcos[i] + od.re*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
106 data[i2 ] = ev.re - od.re*tcos[i] + od.im*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
107 data[i2+1] = -ev.im + od.im*tcos[i] + od.re*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
108 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
109 data[2*i+1]=s->sign_convention*data[2*i+1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
110 if (s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
111 data[0] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
112 data[1] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
113 ff_fft_permute(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
114 ff_fft_calc(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
115 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
116 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
117
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
118 void ff_rdft_calc(RDFTContext *s, FFTSample *data)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
119 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
120 ff_rdft_calc_c(s, data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
121 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
122
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
123 av_cold void ff_rdft_end(RDFTContext *s)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
124 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
125 ff_fft_end(&s->fft);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
126 }