Line data Source code
1 : /******************************************************************************
2 : * ETSI TS 103 634 V1.5.1 *
3 : * Low Complexity Communication Codec Plus (LC3plus) *
4 : * *
5 : * Copyright licence is solely granted through ETSI Intellectual Property *
6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
7 : * estoppel or otherwise. *
8 : ******************************************************************************/
9 :
10 : /* guard against unindended includes */
11 : #ifndef INCLUDED_FROM_IISFFT_C
12 : #error "this file must not be included"
13 : #endif
14 :
15 0 : static void fft60(LC3_FLOAT* in)
16 : {
17 0 : const LC3_INT table1[] = {0, 45, 30, 15, 16, 1, 46, 31, 32, 17, 2, 47, 48, 33, 18, 3, 4, 49, 34, 19,
18 : 20, 5, 50, 35, 36, 21, 6, 51, 52, 37, 22, 7, 8, 53, 38, 23, 24, 9, 54, 39,
19 : 40, 25, 10, 55, 56, 41, 26, 11, 12, 57, 42, 27, 28, 13, 58, 43, 44, 29, 14, 59};
20 0 : const LC3_INT table2[] = {0, 15, 30, 45, 4, 19, 34, 49, 8, 23, 38, 53, 12, 27, 42, 57, 16, 31, 46, 1,
21 : 20, 35, 50, 5, 24, 39, 54, 9, 28, 43, 58, 13, 32, 47, 2, 17, 36, 51, 6, 21,
22 : 40, 55, 10, 25, 44, 59, 14, 29, 48, 3, 18, 33, 52, 7, 22, 37, 56, 11, 26, 41};
23 0 : const LC3_INT a = 4;
24 0 : const LC3_INT b = 15;
25 0 : const LC3_INT L = 60;
26 0 : const LC3_INT* idx1 = table1;
27 0 : const LC3_INT* idx2 = table2;
28 :
29 : LC3_FLOAT temp[30], out[120];
30 : LC3_INT k, l;
31 :
32 0 : for (k = 0; k < a; k++) {
33 0 : for (l = 0; l < b; l++) {
34 0 : temp[2 * l] = in[2 * *idx1];
35 0 : temp[2 * l + 1] = in[2 * *idx1 + 1];
36 0 : idx1 += a;
37 : }
38 :
39 0 : fft15(temp); /* 15-point FFT */
40 0 : idx1 -= L;
41 :
42 0 : for (l = 0; l < b; l++) {
43 0 : in[2 * *idx1] = temp[2 * l];
44 0 : in[2 * *idx1 + 1] = temp[2 * l + 1];
45 0 : idx1 += a;
46 : }
47 0 : idx1 -= L - 1;
48 : }
49 :
50 0 : idx1 -= a;
51 :
52 0 : for (k = 0; k < b; k++) {
53 0 : for (l = 0; l < a; l++) {
54 0 : temp[2 * l] = in[2 * *idx1];
55 0 : temp[2 * l + 1] = in[2 * *idx1++ + 1];
56 : }
57 :
58 0 : fft4(temp); /* 4-point FFT */
59 :
60 0 : for (l = 0; l < a; l++) {
61 0 : out[2 * *idx2] = temp[2 * l];
62 0 : out[2 * *idx2++ + 1] = temp[2 * l + 1];
63 : }
64 : }
65 0 : memmove(in, out, 2 * L * sizeof(LC3_FLOAT));
66 0 : }
67 :
68 0 : static void fft64(LC3_FLOAT* vec)
69 : {
70 0 : const LC3_FLOAT w[] = {
71 : 1.0000000000f, 0.9951847267f, 0.9807852804f, 0.9569403357f, 0.9238795325f, 0.8819212643f, 0.8314696123f,
72 : 0.7730104534f, 0.7071067812f, 0.6343932842f, 0.5555702330f, 0.4713967368f, 0.3826834324f, 0.2902846773f,
73 : 0.1950903220f, 0.0980171403f, 0.0000000000f, -0.0980171403f, -0.1950903220f, -0.2902846773f, -0.3826834324f,
74 : -0.4713967368f, -0.5555702330f, -0.6343932842f, -0.7071067812f, -0.7730104534f, -0.8314696123f, -0.8819212643f,
75 : -0.9238795325f, -0.9569403357f, -0.9807852804f, -0.9951847267f, -1.0000000000f, -0.9951847267f, -0.9807852804f,
76 : -0.9569403357f, -0.9238795325f, -0.8819212643f, -0.8314696123f, -0.7730104534f, -0.7071067812f, -0.6343932842f,
77 : -0.5555702330f, -0.4713967368f, -0.3826834324f, -0.2902846773f, -0.1950903220f, -0.0980171403f};
78 :
79 : LC3_FLOAT temp1[64], temp2[64];
80 : LC3_INT i;
81 :
82 0 : for (i = 0; i < 32; i++) {
83 0 : temp1[2 * i] = vec[4 * i];
84 0 : temp1[2 * i + 1] = vec[4 * i + 1];
85 0 : temp2[2 * i] = vec[4 * i + 2];
86 0 : temp2[2 * i + 1] = vec[4 * i + 3];
87 : }
88 :
89 0 : fft32(temp1);
90 0 : fft32(temp2);
91 :
92 0 : for (i = 0; i < 32; i++) {
93 : LC3_FLOAT re, im, wre, wim, tre, tim;
94 :
95 0 : re = temp2[2 * i];
96 0 : im = temp2[2 * i + 1];
97 :
98 0 : wre = w[i];
99 0 : wim = w[i + 16];
100 :
101 0 : tre = re * wre - im * wim;
102 0 : tim = re * wim + im * wre;
103 :
104 0 : vec[2 * i] = temp1[2 * i] + tre;
105 0 : vec[2 * i + 1] = temp1[2 * i + 1] + tim;
106 0 : vec[2 * i + 64] = temp1[2 * i] - tre;
107 0 : vec[2 * i + 65] = temp1[2 * i + 1] - tim;
108 : }
109 0 : }
110 :
111 0 : static void fft128(LC3_FLOAT* vec)
112 : {
113 0 : const LC3_FLOAT w[] = {
114 : 1.0000000000f, 0.9987954562f, 0.9951847267f, 0.9891765100f, 0.9807852804f, 0.9700312532f, 0.9569403357f,
115 : 0.9415440652f, 0.9238795325f, 0.9039892931f, 0.8819212643f, 0.8577286100f, 0.8314696123f, 0.8032075315f,
116 : 0.7730104534f, 0.7409511254f, 0.7071067812f, 0.6715589548f, 0.6343932842f, 0.5956993045f, 0.5555702330f,
117 : 0.5141027442f, 0.4713967368f, 0.4275550934f, 0.3826834324f, 0.3368898534f, 0.2902846773f, 0.2429801799f,
118 : 0.1950903220f, 0.1467304745f, 0.0980171403f, 0.0490676743f, 0.0000000000f, -0.0490676743f, -0.0980171403f,
119 : -0.1467304745f, -0.1950903220f, -0.2429801799f, -0.2902846773f, -0.3368898534f, -0.3826834324f, -0.4275550934f,
120 : -0.4713967368f, -0.5141027442f, -0.5555702330f, -0.5956993045f, -0.6343932842f, -0.6715589548f, -0.7071067812f,
121 : -0.7409511254f, -0.7730104534f, -0.8032075315f, -0.8314696123f, -0.8577286100f, -0.8819212643f, -0.9039892931f,
122 : -0.9238795325f, -0.9415440652f, -0.9569403357f, -0.9700312532f, -0.9807852804f, -0.9891765100f, -0.9951847267f,
123 : -0.9987954562f, -1.0000000000f, -0.9987954562f, -0.9951847267f, -0.9891765100f, -0.9807852804f, -0.9700312532f,
124 : -0.9569403357f, -0.9415440652f, -0.9238795325f, -0.9039892931f, -0.8819212643f, -0.8577286100f, -0.8314696123f,
125 : -0.8032075315f, -0.7730104534f, -0.7409511254f, -0.7071067812f, -0.6715589548f, -0.6343932842f, -0.5956993045f,
126 : -0.5555702330f, -0.5141027442f, -0.4713967368f, -0.4275550934f, -0.3826834324f, -0.3368898534f, -0.2902846773f,
127 : -0.2429801799f, -0.1950903220f, -0.1467304745f, -0.0980171403f, -0.0490676743f,
128 : };
129 :
130 : LC3_FLOAT temp1[128], temp2[128];
131 : LC3_INT i;
132 :
133 0 : for (i = 0; i < 64; i++) {
134 0 : temp1[2 * i] = vec[4 * i];
135 0 : temp1[2 * i + 1] = vec[4 * i + 1];
136 0 : temp2[2 * i] = vec[4 * i + 2];
137 0 : temp2[2 * i + 1] = vec[4 * i + 3];
138 : }
139 :
140 0 : fft64(temp1);
141 0 : fft64(temp2);
142 :
143 0 : for (i = 0; i < 64; i++) {
144 : LC3_FLOAT re, im, wre, wim, tre, tim;
145 :
146 0 : re = temp2[2 * i];
147 0 : im = temp2[2 * i + 1];
148 :
149 0 : wre = w[i];
150 0 : wim = w[i + 32];
151 :
152 0 : tre = re * wre - im * wim;
153 0 : tim = re * wim + im * wre;
154 :
155 0 : vec[2 * i] = temp1[2 * i] + tre;
156 0 : vec[2 * i + 1] = temp1[2 * i + 1] + tim;
157 0 : vec[2 * i + 128] = temp1[2 * i] - tre;
158 0 : vec[2 * i + 129] = temp1[2 * i + 1] - tim;
159 : }
160 0 : }
|