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 :
12 : /* Union holding buffers to conserve stack memory. */
13 :
14 0 : void processMdct_fx(
15 : #ifdef ENABLE_HR_MODE
16 : Word32 x[], /* i: time input signal */
17 : #else
18 : Word16 x[], /* i: time input signal */
19 : #endif
20 : Word16 x_exp, Word16 N, /* i: block size N */
21 : #ifdef ENABLE_HR_MODE
22 : Word16 hrmode, /* i: indicate high precision */
23 : #endif
24 : #ifdef ENABLE_HR_MODE
25 : const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
26 : #else
27 : const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
28 : #endif
29 : Word16 wLen, /* i: window length */
30 : #ifdef ENABLE_HR_MODE
31 : Word32 mem[], /* i/o: last block of input samples */
32 : #else
33 : Word16 mem[], /* i/o: last block of input samples */
34 : #endif
35 : Word16 memLen, /* i: length of last sample block */
36 : Word32 y[], /* o: spectral data */
37 : Word16 * y_e, /* o: spectal data exponent */
38 : Word8 * scratchBuffer)
39 : {
40 : Counter i;
41 : Word16 z, s, m;
42 : #ifdef ENABLE_HR_MODE
43 : Word32 *buf;
44 : #else
45 : Word16 *buf;
46 : #endif
47 : Word32 *workBuffer;
48 :
49 : #ifdef DYNMEM_COUNT
50 : Dyn_Mem_In("processMdct_fx", sizeof(struct {
51 : Counter i;
52 : Word16 z, s, m;
53 : Word16 *buf;
54 : Word32 *workBuffer;
55 : }));
56 : #endif
57 :
58 : /* Buffers overlap since they are not used at the same time */
59 : #ifdef ENABLE_HR_MODE
60 0 : buf = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */
61 : #else
62 : buf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */
63 : #endif
64 0 : workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN */
65 :
66 : /* Init (constant per sample rate) */
67 0 : z = (N << 1) - wLen; /* number of leading zeros in window */
68 0 : m = N >> 1; /* half block size */
69 :
70 : #ifdef ENABLE_HR_MODE
71 0 : basop_memmove(buf, mem, memLen * sizeof(Word32));
72 :
73 0 : basop_memmove(&buf[memLen], x, (N - memLen) * sizeof(Word32));
74 :
75 0 : basop_memmove(mem, &x[N - memLen], memLen * sizeof(Word32));
76 : #else
77 : basop_memmove(buf, mem, memLen * sizeof(Word16));
78 :
79 : basop_memmove(&buf[memLen], x, (N - memLen) * sizeof(Word16));
80 :
81 : basop_memmove(mem, &x[N - memLen], memLen * sizeof(Word16));
82 : #endif
83 :
84 : #ifdef ENABLE_HR_MODE
85 0 : if (hrmode)
86 : {
87 0 : FOR (i = 0; i < m; i++)
88 : {
89 0 : y[m + i] = Msu_32_32_0(Mpy_32_32_0(w[i], buf[i]), w[2 * m - 1 - i], buf[2 * m - 1 - i]); move32();
90 : }
91 :
92 0 : FOR (i = 0; i < z; i++)
93 : {
94 0 : y[m - 1 - i] = Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]); move32();
95 : }
96 :
97 0 : FOR (i = i; i < m; i++)
98 : {
99 0 : y[m - 1 - i] = Mac_32_32_0(Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]), w[4 * m - 1 - i], x[4 * m - memLen - 1 - i]); move32();
100 : }
101 : } else {
102 0 : FOR (i = 0; i < m; i++)
103 : {
104 0 : y[m + i] = L_msu0(L_mult0(round_fx_sat(buf[i]), round_fx(w[i])), round_fx_sat(buf[2 * m - 1 - i]), round_fx(w[2 * m - 1 - i])); move32();
105 : }
106 :
107 0 : FOR (i = 0; i < z; i++)
108 : {
109 0 : y[m - 1 - i] = L_mult0(round_fx_sat(x[2 * m - memLen + i]), round_fx(w[2 * m + i])); move32();
110 : }
111 :
112 0 : FOR (i = i; i < m; i++)
113 : {
114 0 : y[m - 1 - i] = L_mac0(L_mult0(round_fx_sat(x[2 * m - memLen + i]), round_fx(w[2 * m + i])), round_fx_sat(x[4 * m - memLen - 1 - i]),
115 0 : round_fx(w[4 * m - 1 - i])); move32();
116 : }
117 : }
118 : #else
119 : /* regular resolution only */
120 : FOR (i = 0; i < m; i++)
121 : {
122 : y[m + i] = L_msu0(L_mult0(buf[i], w[i]), buf[2 * m - 1 - i], w[2 * m - 1 - i]); move32();
123 : }
124 :
125 : FOR (i = 0; i < z; i++)
126 : {
127 : y[m - 1 - i] = L_mult0(x[2 * m - memLen + i], w[2 * m + i]); move32();
128 : }
129 :
130 : FOR (i = i; i < m; i++)
131 : {
132 : y[m - 1 - i] = L_mac0(L_mult0(x[2 * m - memLen + i], w[2 * m + i]), x[4 * m - memLen - 1 - i],
133 : w[4 * m - 1 - i]); move32();
134 : }
135 : #endif
136 :
137 0 : s = s_max(0, getScaleFactor32_lc3plus(y, N));
138 0 : FOR (i = 0; i < N; i++)
139 : {
140 0 : y[i] = L_shl(y[i], s); move32();
141 : }
142 :
143 0 : *y_e = sub(sub(x_exp, 2), s);
144 :
145 : /* N=20 only for 2.5ms possible */
146 : /* maybe implement this a pre init of shift */
147 0 : if (sub(N, 20) <= 0)
148 : {
149 0 : *y_e = add(*y_e, 2);
150 : }
151 0 : else if (sub(N, 120) <= 0)
152 : {
153 0 : *y_e = add(*y_e, 1);
154 : }
155 : #ifdef ENABLE_HR_MODE
156 0 : dct_IV(y, y_e, N,
157 : hrmode,
158 : workBuffer);
159 : #else
160 : dct_IV(y, y_e, N, workBuffer);
161 : #endif
162 :
163 : #ifdef DYNMEM_COUNT
164 : Dyn_Mem_Out();
165 : #endif
166 0 : }
167 :
|