annotate rdft.c @ 10463:9f35b262d3f0 libavcodec

Commit some functions that are used by both SIPR and AMR. Based on AMR SoC code by Robert Swain and Colin McQuillan.
author vitor
date Tue, 27 Oct 2009 23:53:18 +0000
parents 8fd8f6c1cdcc
children 63910f7ba293
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 */
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
30 #if !CONFIG_HARDCODED_TABLES
10407
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
31 SINTABLE(16);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
32 SINTABLE(32);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
33 SINTABLE(64);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
34 SINTABLE(128);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
35 SINTABLE(256);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
36 SINTABLE(512);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
37 SINTABLE(1024);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
38 SINTABLE(2048);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
39 SINTABLE(4096);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
40 SINTABLE(8192);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
41 SINTABLE(16384);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
42 SINTABLE(32768);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
43 SINTABLE(65536);
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
44 #endif
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
45 SINTABLE_CONST 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
46 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
47 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
48 };
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 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
51 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
52 int n = 1 << nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
53 int i;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
54 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
55
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
56 s->nbits = nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
57 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
58 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
59
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
60 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
61 return -1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
62
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
63 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
64 return -1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
65
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
66 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
67 s->tsin = ff_sin_tabs[nbits-4]+(trans == RDFT || trans == IRIDFT)*(n>>2);
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
68 #if !CONFIG_HARDCODED_TABLES
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
69 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
70 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
71 }
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
72 #endif
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
73 return 0;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
74 }
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 /** 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
77 * 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
78 * 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
79 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
80 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
81 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
82 int i, i1, i2;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
83 FFTComplex ev, od;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
84 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
85 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
86 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
87 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
88 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
89
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
90 if (!s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
91 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
92 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
93 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
94 /* 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
95 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
96 ev.re = data[0];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
97 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
98 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
99 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
100 i1 = 2*i;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
101 i2 = n-i1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
102 /* 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
103 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
104 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
105 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
106 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
107 /* 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
108 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
109 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
110 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
111 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
112 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
113 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
114 if (s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
115 data[0] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
116 data[1] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
117 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
118 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
119 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
120 }
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 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
123 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
124 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
125 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
126
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
127 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
128 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
129 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
130 }