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 "options.h"
11 : #include "wmc_auto.h"
12 : #include "functions.h"
13 :
14 : LC3_FLOAT pc_peak_detector(LC3_FLOAT *q_d_prev, LC3_INT32 yLen);
15 :
16 0 : void processPcClassify_fl(LC3_INT32 pitch_present, LC3_INT32 frame_dms, LC3_FLOAT *q_d_prev, LC3_FLOAT *q_old_res, LC3_INT32 yLen, LC3_INT32 spec_inv_idx, LC3_FLOAT stab_fac, LC3_INT32 *bfi)
17 : {
18 : LC3_INT32 maxPitchBin, xover, i;
19 : LC3_FLOAT part_nrg, full_nrg;
20 :
21 0 : part_nrg = 0; full_nrg = 0;
22 :
23 0 : if (spec_inv_idx < (4 * frame_dms / 10))
24 : {
25 0 : if (stab_fac < 0.5)
26 : {
27 0 : *bfi = 1;
28 0 : } else if (pitch_present == 1)
29 : {
30 0 : maxPitchBin = 8;
31 0 : if (frame_dms == 50)
32 : {
33 0 : maxPitchBin = 4;
34 : }
35 0 : xover = pc_peak_detector(q_d_prev, yLen);
36 0 : if (spec_inv_idx < xover || spec_inv_idx < maxPitchBin)
37 : {
38 0 : *bfi = 1;
39 : }
40 : } else {
41 0 : for (i = 0; i < spec_inv_idx; i++)
42 : {
43 0 : part_nrg += LC3_POW(q_old_res[i], 2);
44 : }
45 :
46 0 : for (i = 0; i < yLen; i++)
47 : {
48 0 : full_nrg += LC3_POW(q_old_res[i], 2);
49 : }
50 :
51 0 : if (part_nrg < (0.3 * full_nrg))
52 : {
53 0 : *bfi = 1;
54 : }
55 : }
56 : }
57 0 : }
58 :
59 0 : LC3_FLOAT pc_peak_detector(LC3_FLOAT *q_d_prev, LC3_INT32 yLen)
60 : {
61 : LC3_INT32 block_size, thresh1, i, peak, j, k;
62 : LC3_FLOAT fac, mean_block_nrg, cur_max, block_cent, maxPeak, next_max, prev_max;
63 :
64 0 : mean_block_nrg = 0;
65 :
66 0 : block_size = 3;
67 0 : thresh1 = 8;
68 0 : fac = 0.3;
69 :
70 0 : for (i = 0; i < yLen; i++)
71 : {
72 0 : mean_block_nrg += LC3_POW(q_d_prev[i], 2);
73 : }
74 :
75 0 : mean_block_nrg /= yLen;
76 :
77 0 : maxPeak = 0;
78 0 : peak = 0;
79 :
80 0 : if (LC3_FABS(q_d_prev[0]) > LC3_FABS(q_d_prev[1]))
81 : {
82 0 : block_cent = LC3_POW(q_d_prev[0], 2) + LC3_POW(q_d_prev[1], 2);
83 :
84 0 : if ((block_cent / block_size) > (thresh1 * mean_block_nrg))
85 : {
86 0 : cur_max = MAX(LC3_FABS(q_d_prev[0]), LC3_FABS(q_d_prev[1]));
87 0 : next_max = array_max_abs(&q_d_prev[2], 3);
88 :
89 0 : if (cur_max > next_max)
90 : {
91 0 : maxPeak = block_cent;
92 0 : peak = 1;
93 : }
94 : }
95 : }
96 :
97 0 : for (i = 0; i < block_size; i++)
98 : {
99 0 : if ((LC3_FABS(q_d_prev[i + 1]) >= LC3_FABS(q_d_prev[i])) && LC3_FABS(q_d_prev[i + 1]) >= LC3_FABS(q_d_prev[i + 2]))
100 : {
101 0 : block_cent = 0;
102 0 : for (j = i; j < i + block_size; j++)
103 : {
104 0 : block_cent += LC3_POW(q_d_prev[j], 2);
105 : }
106 :
107 0 : if ((block_cent / block_size) > (thresh1 * mean_block_nrg))
108 : {
109 0 : cur_max = array_max_abs(&q_d_prev[i], block_size);
110 0 : prev_max = 0;
111 :
112 0 : for (k = i - block_size; k < i; k++)
113 : {
114 0 : if (k > 0)
115 : {
116 0 : prev_max = MAX(LC3_FABS(q_d_prev[k]), prev_max);
117 : }
118 : }
119 0 : next_max = array_max_abs(&q_d_prev[i + block_size], block_size);
120 :
121 0 : if ((cur_max >= prev_max) && (cur_max > next_max))
122 : {
123 0 : if (block_cent > (fac * maxPeak))
124 : {
125 0 : peak = i + block_size - 1;
126 0 : if (block_cent >= maxPeak)
127 : {
128 0 : maxPeak = block_cent;
129 : }
130 : }
131 : }
132 : }
133 : }
134 : }
135 :
136 0 : for (i = block_size; i < yLen - (2 * block_size); i++)
137 : {
138 0 : if ((LC3_FABS(q_d_prev[i + 1]) >= LC3_FABS(q_d_prev[i])) && LC3_FABS(q_d_prev[i + 1]) >= LC3_FABS(q_d_prev[i + 2]))
139 : {
140 0 : block_cent = 0;
141 0 : for (j = i; j < i + block_size; j++)
142 : {
143 0 : block_cent += LC3_POW(q_d_prev[j], 2);
144 : }
145 :
146 0 : if ((block_cent / block_size) > (thresh1 * mean_block_nrg))
147 : {
148 0 : cur_max = array_max_abs(&q_d_prev[i], block_size);
149 0 : prev_max = array_max_abs(&q_d_prev[i - block_size], block_size);
150 0 : next_max = array_max_abs(&q_d_prev[i + block_size], block_size);
151 :
152 0 : if ((cur_max >= prev_max) && (cur_max > next_max))
153 : {
154 0 : if (block_cent > (fac * maxPeak))
155 : {
156 0 : peak = i + block_size - 1;
157 0 : if (block_cent >= maxPeak)
158 : {
159 0 : maxPeak = block_cent;
160 : }
161 : }
162 : }
163 : }
164 : }
165 : }
166 :
167 0 : return peak;
168 : }
169 :
|