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 : #include "functions.h"
11 : #include "rom_basop_util_lc3plus.h"
12 :
13 :
14 0 : void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */
15 : Word16 *pDat_e, /* i/o: pointer to data exponent */
16 : Word16 L, /* i : length of block */
17 : #ifdef ENABLE_HR_MODE
18 : Word16 hrmode, /* indicate high precision usage */
19 : #endif
20 : Word32 *workBuffer) /* : size of L */
21 :
22 : {
23 : Word16 sin_step;
24 : Word16 idx;
25 : Word16 M_var;
26 : Word16 M2;
27 :
28 : Word32 *pDat_0;
29 : Word32 *pDat_1;
30 :
31 : Word32 accu1;
32 : Word32 accu2;
33 : Word32 accu3;
34 : Word32 accu4;
35 :
36 : Word32 i;
37 :
38 : #ifdef ENABLE_HR_MODE
39 : const PWord32 *twiddle;
40 : const PWord32 *sin_twiddle;
41 : #else
42 : const PWord16 *twiddle;
43 : const PWord16 *sin_twiddle;
44 : #endif
45 :
46 : #ifdef ENABLE_DCTIV_RESCALE
47 : Word16 scale;
48 : #endif
49 :
50 : #ifdef DYNMEM_COUNT
51 : #ifdef ENABLE_HR_MODE
52 : Dyn_Mem_In("dct_IV", sizeof(struct {
53 : Word16 sin_step;
54 : Word16 idx;
55 : Counter i;
56 : Word16 M_var;
57 : Word16 M2;
58 :
59 : Word32 *pDat_0;
60 : Word32 *pDat_1;
61 :
62 : Word32 accu1;
63 : Word32 accu2;
64 : Word32 accu3;
65 : Word32 accu4;
66 :
67 : const PWord32 *twiddle;
68 : const PWord32 *sin_twiddle;
69 : }));
70 :
71 : #else
72 : Dyn_Mem_In("dct_IV", sizeof(struct {
73 : Word16 sin_step;
74 : Word16 idx;
75 : Counter i;
76 : Word16 M_var;
77 : Word16 M2;
78 :
79 : Word32 *pDat_0;
80 : Word32 *pDat_1;
81 :
82 : Word32 accu1;
83 : Word32 accu2;
84 : Word32 accu3;
85 : Word32 accu4;
86 :
87 : const PWord16 *twiddle;
88 : const PWord16 *sin_twiddle;
89 : }));
90 : #endif /* ENABLE_HR_MODE */
91 : #endif /* DYNMEM_COUNT */
92 :
93 0 : M_var = shr_pos_pos(L, 1);
94 0 : M2 = sub(M_var, 1);
95 :
96 0 : BASOP_getTables(&twiddle, &sin_twiddle, &sin_step, L);
97 :
98 0 : pDat_0 = &pDat[0];
99 0 : pDat_1 = &pDat[L - 2];
100 :
101 0 : FOR (i = 0; i < M2; i += 2)
102 : {
103 : #ifdef ENABLE_HR_MODE
104 0 : if (hrmode) {
105 0 : cplxMpy32_32_32_2(accu1, accu2, pDat_1[1], pDat_0[0], twiddle[i].v.re, twiddle[i].v.im);
106 0 : cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im);
107 : } else {
108 0 : cplxMpy32_32_16_2(accu1, accu2, pDat_1[1], pDat_0[0], round_fx_sat(twiddle[i].v.re), round_fx_sat(twiddle[i].v.im));
109 0 : cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_0[1], round_fx_sat(twiddle[i + 1].v.re), round_fx_sat(twiddle[i + 1].v.im));
110 : }
111 : #else
112 : cplxMpy32_32_16_2(accu1, accu2, pDat_1[1], pDat_0[0], twiddle[i].v.re, twiddle[i].v.im);
113 : cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im);
114 : #endif
115 :
116 0 : pDat_0[0] = accu2; move32();
117 0 : pDat_0[1] = accu1; move32();
118 0 : pDat_1[0] = accu4; move32();
119 0 : pDat_1[1] = L_negate(accu3); move32();
120 :
121 0 : pDat_0 = pDat_0 + 2;
122 0 : pDat_1 = pDat_1 - 2;
123 : }
124 :
125 : #ifdef ENABLE_DCTIV_RESCALE
126 0 : if (hrmode)
127 : {
128 :
129 0 : scale = s_max(getScaleFactor32_lc3plus(pDat, L), 0); move16();
130 :
131 0 : FOR (i = 0; i < L; i++)
132 : {
133 0 : pDat[i] = L_shl_pos(pDat[i], scale); move32();
134 : }
135 :
136 0 : *pDat_e = sub(*pDat_e, scale); move16();
137 : }
138 : #endif
139 :
140 0 : BASOP_cfft_lc3plus(&pDat[0], &pDat[1], M_var, 2, pDat_e, workBuffer);
141 :
142 0 : pDat_0 = &pDat[0];
143 0 : pDat_1 = &pDat[L - 2];
144 :
145 0 : idx = sin_step;
146 0 : M2 = sub(shr_pos_pos(add(M_var, 1), 1), 1);
147 :
148 : /* Sin and Cos values are 0.0f and 1.0f */
149 : #ifdef ENABLE_HR_MODE
150 0 : cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
151 : #else
152 : cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
153 : #endif
154 :
155 0 : pDat_1[1] = L_negate(L_shr_pos(pDat_0[1], 1)); move32();
156 0 : pDat_0[0] = L_shr_pos(pDat_0[0], 1); move32();
157 :
158 0 : FOR (i = 1; i < M2; i++)
159 : {
160 0 : pDat_0[1] = accu3; move32();
161 0 : pDat_1[0] = accu4; move32();
162 :
163 0 : pDat_0 = pDat_0 + 2;
164 0 : pDat_1 = pDat_1 - 2;
165 :
166 : #ifdef ENABLE_HR_MODE
167 0 : cplxMpy32_32_32_2(accu1, accu2, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
168 : #else
169 : cplxMpy32_32_16_2(accu1, accu2, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
170 : #endif
171 :
172 0 : idx += sin_step;
173 :
174 : #ifdef ENABLE_HR_MODE
175 0 : cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
176 : #else
177 : cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
178 : #endif
179 :
180 0 : pDat_1[1] = L_negate(accu1); move32();
181 0 : pDat_0[0] = accu2; move32();
182 : }
183 :
184 0 : pDat_0[1] = accu3; move32();
185 0 : pDat_1[0] = accu4; move32();
186 :
187 0 : pDat_0 = pDat_0 + 2;
188 0 : pDat_1 = pDat_1 - 2;
189 :
190 : #ifdef ENABLE_HR_MODE
191 0 : cplxMpy32_32_32_2(accu3, accu4, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
192 : #else
193 : cplxMpy32_32_16_2(accu3, accu4, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im);
194 : #endif
195 :
196 : /* Last Sin and Cos value pair are the same */
197 : #ifdef ENABLE_HR_MODE
198 0 : accu1 = L_shr_pos(Mpy_32_32_lc3plus(pDat_1[0], TWIDDLE), 1);
199 0 : accu2 = L_shr_pos(Mpy_32_32_lc3plus(pDat_1[1], TWIDDLE), 1);
200 : #else
201 : accu1 = L_shr_pos(Mpy_32_16_lc3plus(pDat_1[0], TWIDDLE), 1);
202 : accu2 = L_shr_pos(Mpy_32_16_lc3plus(pDat_1[1], TWIDDLE), 1);
203 : #endif
204 :
205 0 : pDat_1[0] = L_add(accu1, accu2); move32();
206 0 : pDat_0[1] = L_sub(accu1, accu2); move32();
207 :
208 0 : pDat_1[1] = L_negate(accu3); move32();
209 0 : pDat_0[0] = accu4; move32();
210 :
211 : /* twiddeling scale is 2 */
212 0 : *pDat_e = add(*pDat_e, 2); move16();
213 :
214 : #ifdef DYNMEM_COUNT
215 : Dyn_Mem_Out();
216 : #endif
217 0 : }
218 :
|