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 0 : void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_idx, const Word16 near_nyquist_index,
13 : const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp
14 : #ifdef ENABLE_HR_MODE
15 : , Word16 frame_dms, Word16 hrmode)
16 : #else
17 : )
18 : #endif
19 : {
20 0 : *near_nyquist_flag = 0;
21 : #ifdef ENABLE_HR_MODE
22 0 : IF (hrmode == 0){
23 : #endif
24 0 : IF (sub(fs_idx, 4) < 0)
25 : {
26 : Dyn_Mem_Deluxe_In(
27 : Word16 i;
28 : Word16 nrg_above_thresh;
29 : Word16 ener_low_exp;
30 : Word16 ener_high_exp;
31 : Word16 comp_energy_exp;
32 : Word32 comp_energy;
33 : Word32 ener_low;
34 : Word32 ener_high;
35 : );
36 :
37 0 : ener_low = 0; move32();
38 0 : ener_low_exp = 0; move16();
39 0 : FOR (i = 0; i < near_nyquist_index; i++)
40 : {
41 0 : ener_low = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_low, ener_low_exp, &ener_low_exp);
42 : }
43 :
44 0 : ener_high = 0; move32();
45 0 : ener_high_exp = 0; move16();
46 0 : FOR (i = near_nyquist_index; i < bands_number; i++)
47 : {
48 0 : ener_high = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_high, ener_high_exp, &ener_high_exp);
49 : }
50 :
51 0 : comp_energy = Mpy_32_16_lc3plus(ener_low, NN_thresh); /* Mpy_32_16_lc3plus -> 32Q15 */
52 0 : comp_energy_exp = add(add(ener_low_exp, NN_thresh_exp),15);
53 :
54 0 : nrg_above_thresh = BASOP_Util_Cmp_Mant32Exp_lc3plus(ener_high, ener_high_exp, comp_energy, comp_energy_exp); /* 1 if firstNumber > secondNumber */
55 :
56 0 : if (sub(nrg_above_thresh, 1) == 0)
57 : {
58 0 : *near_nyquist_flag = 1;
59 : }
60 :
61 : Dyn_Mem_Deluxe_Out();
62 : }
63 : #ifdef ENABLE_HR_MODE
64 : }
65 : ELSE // hrmode == 1
66 : {
67 : // inverse spectral flatness = mean(energy) ./ 2^(mean(log2(energy)));
68 : Word32 td_thresh;
69 :
70 0 : SWITCH (frame_dms)
71 : {
72 0 : case 25:
73 0 : td_thresh = TD_HR_thresh_2_5ms;
74 0 : BREAK;
75 0 : case 50:
76 0 : td_thresh = TD_HR_thresh_5ms;
77 0 : BREAK;
78 0 : case 75:
79 0 : td_thresh = TD_HR_thresh_7_5ms;
80 0 : BREAK;
81 0 : default: /* 100 */
82 0 : td_thresh = TD_HR_thresh_10ms;
83 0 : BREAK;
84 : }
85 :
86 0 : Word16 mean_ener_exp = 0;
87 :
88 0 : Word32 sum_ener = 0; move32();
89 0 : Word16 sum_ener_exp = 0; move16();
90 0 : FOR (Word16 i = 0; i < bands_number; i++)
91 : {
92 0 : sum_ener = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, sum_ener, sum_ener_exp, &sum_ener_exp);
93 : }
94 :
95 0 : Word16 denom = sub(14,norm_s(bands_number));
96 0 : IF (sub(frame_dms, 50) == 0){
97 0 : denom = sub(15,norm_s(bands_number)); move16();
98 : }
99 :
100 0 : Word32 mean_ener = L_shr(sum_ener, denom); move32(); // = sum_ener / bands_number
101 0 : mean_ener_exp = sum_ener_exp; move16();
102 :
103 0 : Word32 sum_ener_log2 = 0;move32();
104 0 : Word16 sum_ener_log2_exp = 0;move16();
105 0 : Word32 mean_ener_log2 = 0;move32();
106 :
107 0 : FOR (Word16 i = 0; i < bands_number; i++)
108 : {
109 0 : IF (ener_fx[i] != 0) {
110 0 : Word32 log2Value = L_add(BASOP_Util_Log2_lc3plus(ener_fx[i]), L_shl_pos(L_deposit_l(ener_fx_exp), 25));
111 : /* input argument is in Q7.25 , returns pow(2,(x/64)
112 : floatingpoint value log2_fl = log2Value/pow(2,31-6) */
113 0 : sum_ener_log2 = BASOP_Util_Add_Mant32Exp_lc3plus(log2Value, 6, sum_ener_log2, sum_ener_log2_exp, &sum_ener_log2_exp); move32();
114 : }
115 : }
116 0 : mean_ener_log2 = L_shr(sum_ener_log2, denom); move32(); //mean_ener_log2 = sum_ener_log2 / bands_number
117 0 : Word16 mean_ener_log2_exp = sum_ener_log2_exp;
118 0 : Word32 mean_ener_log2_fl = L_shr_pos(mean_ener_log2 ,s_min(31, sub(31,mean_ener_log2_exp))); //mean_ener_log2_fl = mean_ener_log2 / 2^(31-mean_ener_log2_exp)
119 0 : Word32 inv_flatness = 0;
120 0 : if (L_sub(norm_l(mean_ener),sub(sub(mean_ener_exp,31),mean_ener_log2_fl)) < 0 ) {
121 0 : inv_flatness = maxWord32;
122 : }
123 : else {
124 0 : inv_flatness = L_shl(mean_ener, s_max(-31,sub(sub(mean_ener_exp,31),mean_ener_log2_fl)));
125 : }
126 0 : IF (L_sub(inv_flatness, td_thresh) > 0) {
127 0 : *near_nyquist_flag = 1; move16();
128 : }
129 : }
130 : #endif // ENABLE_HR_MODE
131 0 : }
|