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 "defines.h"
11 : #include "functions.h"
12 :
13 0 : void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 d2_fx_exp, Word16 n_bands,
14 : Word16 lpc_order, Word8 *scratchBuffer)
15 : {
16 : Counter i;
17 : Word16 s;
18 : Word16 n_bands2;
19 : Word32 * x;
20 : const Word32 *inv_odft_twiddle_re;
21 : const Word32 *inv_odft_twiddle_im;
22 : Word8 * buffer_BASOP_rfftN;
23 :
24 :
25 : #ifdef DYNMEM_COUNT
26 : Dyn_Mem_In("processInverseODFT_fx", sizeof(struct {
27 : Counter i;
28 : Word16 s;
29 : Word16 n_bands2;
30 : Word32 * x;
31 : const Word32 *inv_odft_twiddle_re;
32 : const Word32 *inv_odft_twiddle_im;
33 : Word8 * buffer_BASOP_rfftN;
34 : Word32 * params[2];
35 : }));
36 : #endif
37 :
38 0 : x = scratchAlign(scratchBuffer, 0); /* Size = 320 bytes */
39 0 : buffer_BASOP_rfftN = scratchAlign(x, sizeof(*x) * (MAX_BANDS_NUMBER_PLC + MAX_BANDS_NUMBER_PLC/2)); /* Size = 480 bytes */
40 :
41 0 : ASSERT(lpc_order <= M);
42 0 : ASSERT(n_bands == 80 || n_bands == 60 || n_bands == 40 || n_bands == 20);
43 :
44 0 : n_bands2 = shr_pos_pos(n_bands, 1);
45 :
46 0 : test();
47 0 : IF (sub(n_bands, 20) == 0 || sub(n_bands, 60) == 0)
48 : {
49 : /* sort input samples */
50 0 : FOR (i = 0; i < n_bands2; i++)
51 : {
52 0 : x[2*i] = d2_fx[2 * i]; move32();
53 0 : x[2*i+1] = 0; move32();
54 0 : x[n_bands + 2*i] = d2_fx[n_bands - 1 - 2 * i]; move32();
55 0 : x[n_bands + 2*i + 1] = 0; move32();
56 : }
57 0 : BASOP_cfft_lc3plus(&x[0], &x[1], n_bands, 2, &d2_fx_exp, (Word32*)buffer_BASOP_rfftN);
58 : }
59 : ELSE
60 : {
61 : /* sort input samples */
62 0 : FOR (i = 0; i < n_bands2; i++)
63 : {
64 0 : x[i] = d2_fx[2 * i]; move32();
65 0 : x[n_bands2 + i] = d2_fx[n_bands - 1 - 2 * i]; move32();
66 : }
67 :
68 0 : BASOP_rfftN(x, n_bands, &d2_fx_exp, buffer_BASOP_rfftN);
69 : }
70 :
71 0 : inv_odft_twiddle_re = inv_odft_twiddle_80_re;
72 0 : inv_odft_twiddle_im = inv_odft_twiddle_80_im;
73 0 : IF (sub(n_bands, 20) == 0)
74 : {
75 0 : inv_odft_twiddle_re = inv_odft_twiddle_20_re;
76 0 : inv_odft_twiddle_im = inv_odft_twiddle_20_im;
77 : }
78 0 : ELSE IF (sub(n_bands, 40) == 0)
79 : {
80 0 : inv_odft_twiddle_re = inv_odft_twiddle_40_re;
81 0 : inv_odft_twiddle_im = inv_odft_twiddle_40_im;
82 : }
83 0 : ELSE IF (sub(n_bands, 60) == 0)
84 : {
85 0 : inv_odft_twiddle_re = inv_odft_twiddle_60_re;
86 0 : inv_odft_twiddle_im = inv_odft_twiddle_60_im;
87 : }
88 :
89 0 : s = norm_l(x[0]);
90 :
91 : /* imag[0] is always zero */
92 0 : r_fx[0] = L_shl_pos(x[0], s); move32();
93 :
94 : /* r_fx[0] = r_fx[0] * 1.0001 */
95 0 : r_fx[0] = Mpy_32_32_lc3plus(r_fx[0], 0x4001A36E); move32();
96 0 : IF (norm_l(r_fx[0]) > 0)
97 : {
98 0 : r_fx[0] = L_shl_pos(r_fx[0], 1);
99 : }
100 : ELSE
101 : {
102 0 : s = sub(s, 1);
103 : }
104 :
105 : /* post-twiddle */
106 0 : FOR (i = 1; i <= lpc_order; i++)
107 : {
108 0 : r_fx[i] = L_add(Mpy_32_32_lc3plus(L_shl(x[2 * i], s), inv_odft_twiddle_re[i - 1]),
109 0 : Mpy_32_32_lc3plus(L_shl(x[2 * i + 1], s), inv_odft_twiddle_im[i - 1])); move32();
110 : }
111 :
112 0 : *r_fx_exp = sub(d2_fx_exp, s); move16();
113 :
114 : /* r_fx[0] must not be zero */
115 0 : IF (r_fx[0] == 0)
116 : {
117 0 : r_fx[0] = (Word32)0x7FFFFFFF; move32();
118 0 : FOR (i = 1; i <= lpc_order; i++)
119 : {
120 0 : r_fx[i] = 0; move32();
121 : }
122 0 : *r_fx_exp = 0; move16();
123 : }
124 :
125 : #ifdef DYNMEM_COUNT
126 : Dyn_Mem_Out();
127 : #endif
128 0 : }
129 :
130 :
|