xref: /aosp_15_r20/external/libldac/src/sigana_ldac.c (revision aef9bcd9217ad2365ebc8e70efaf94b64e04df14)
1*aef9bcd9SKiyoung Kim /*
2*aef9bcd9SKiyoung Kim  * Copyright (C) 2003 - 2016 Sony Corporation
3*aef9bcd9SKiyoung Kim  *
4*aef9bcd9SKiyoung Kim  * Licensed under the Apache License, Version 2.0 (the "License");
5*aef9bcd9SKiyoung Kim  * you may not use this file except in compliance with the License.
6*aef9bcd9SKiyoung Kim  * You may obtain a copy of the License at
7*aef9bcd9SKiyoung Kim  *
8*aef9bcd9SKiyoung Kim  *      http://www.apache.org/licenses/LICENSE-2.0
9*aef9bcd9SKiyoung Kim  *
10*aef9bcd9SKiyoung Kim  * Unless required by applicable law or agreed to in writing, software
11*aef9bcd9SKiyoung Kim  * distributed under the License is distributed on an "AS IS" BASIS,
12*aef9bcd9SKiyoung Kim  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*aef9bcd9SKiyoung Kim  * See the License for the specific language governing permissions and
14*aef9bcd9SKiyoung Kim  * limitations under the License.
15*aef9bcd9SKiyoung Kim  */
16*aef9bcd9SKiyoung Kim 
17*aef9bcd9SKiyoung Kim #include "ldac.h"
18*aef9bcd9SKiyoung Kim 
19*aef9bcd9SKiyoung Kim 
20*aef9bcd9SKiyoung Kim #define LDAC_TH_LOWENERGY_L _scalar(225.47)
21*aef9bcd9SKiyoung Kim #define LDAC_TH_LOWENERGY_M _scalar(897.61)
22*aef9bcd9SKiyoung Kim #define LDAC_TH_LOWENERGY_H _scalar(3573.44)
23*aef9bcd9SKiyoung Kim 
24*aef9bcd9SKiyoung Kim #define LDAC_TH_CENTROID    _scalar(45.0)
25*aef9bcd9SKiyoung Kim #define LDAC_TH_ZERODIV     _scalar(1.0e-6)
26*aef9bcd9SKiyoung Kim 
27*aef9bcd9SKiyoung Kim /***************************************************************************************************
28*aef9bcd9SKiyoung Kim     Calculate Pseudo Spectrum and Low Band Energy
29*aef9bcd9SKiyoung Kim ***************************************************************************************************/
calc_mdct_pseudo_spectrum_ldac(SCALAR * p_spec,SCALAR * p_psd,int n)30*aef9bcd9SKiyoung Kim static SCALAR calc_mdct_pseudo_spectrum_ldac(
31*aef9bcd9SKiyoung Kim SCALAR *p_spec,
32*aef9bcd9SKiyoung Kim SCALAR *p_psd,
33*aef9bcd9SKiyoung Kim int n)
34*aef9bcd9SKiyoung Kim {
35*aef9bcd9SKiyoung Kim     int isp;
36*aef9bcd9SKiyoung Kim     SCALAR low_energy, tmp;
37*aef9bcd9SKiyoung Kim     SCALAR y0, y1, y2;
38*aef9bcd9SKiyoung Kim 
39*aef9bcd9SKiyoung Kim     {
40*aef9bcd9SKiyoung Kim         y1 = p_spec[0];
41*aef9bcd9SKiyoung Kim         y2 = p_spec[1];
42*aef9bcd9SKiyoung Kim         tmp = y1 * y1 + y2 * y2;
43*aef9bcd9SKiyoung Kim         low_energy = tmp;
44*aef9bcd9SKiyoung Kim         p_psd[0] = sqrt(tmp);
45*aef9bcd9SKiyoung Kim     }
46*aef9bcd9SKiyoung Kim 
47*aef9bcd9SKiyoung Kim     for (isp = 1; isp < LDAC_NSP_LOWENERGY; isp++) {
48*aef9bcd9SKiyoung Kim         y0 = y1;
49*aef9bcd9SKiyoung Kim         y1 = y2;
50*aef9bcd9SKiyoung Kim         y2 = p_spec[isp+1];
51*aef9bcd9SKiyoung Kim         tmp = y1 * y1 + (y0-y2) * (y0-y2);
52*aef9bcd9SKiyoung Kim         low_energy += tmp;
53*aef9bcd9SKiyoung Kim         p_psd[isp] = sqrt(tmp);
54*aef9bcd9SKiyoung Kim     }
55*aef9bcd9SKiyoung Kim 
56*aef9bcd9SKiyoung Kim     for (isp = LDAC_NSP_LOWENERGY; isp < n-1; isp++) {
57*aef9bcd9SKiyoung Kim         y0 = y1;
58*aef9bcd9SKiyoung Kim         y1 = y2;
59*aef9bcd9SKiyoung Kim         y2 = p_spec[isp+1];
60*aef9bcd9SKiyoung Kim         tmp = y1 * y1 + (y0-y2) * (y0-y2);
61*aef9bcd9SKiyoung Kim         p_psd[isp] = sqrt(tmp);
62*aef9bcd9SKiyoung Kim     }
63*aef9bcd9SKiyoung Kim 
64*aef9bcd9SKiyoung Kim     {
65*aef9bcd9SKiyoung Kim         tmp = y1 * y1 + y2 * y2;
66*aef9bcd9SKiyoung Kim         p_psd[n-1] = sqrt(tmp);
67*aef9bcd9SKiyoung Kim     }
68*aef9bcd9SKiyoung Kim 
69*aef9bcd9SKiyoung Kim     return low_energy;
70*aef9bcd9SKiyoung Kim }
71*aef9bcd9SKiyoung Kim 
72*aef9bcd9SKiyoung Kim /***************************************************************************************************
73*aef9bcd9SKiyoung Kim     Calculate Pseudo Spectrum Centroid
74*aef9bcd9SKiyoung Kim ***************************************************************************************************/
calc_spectral_centroid_ldac(SCALAR * p_spec,int nsp)75*aef9bcd9SKiyoung Kim static SCALAR calc_spectral_centroid_ldac(
76*aef9bcd9SKiyoung Kim SCALAR *p_spec,
77*aef9bcd9SKiyoung Kim int nsp)
78*aef9bcd9SKiyoung Kim {
79*aef9bcd9SKiyoung Kim     int isp;
80*aef9bcd9SKiyoung Kim     SCALAR centroid;
81*aef9bcd9SKiyoung Kim     SCALAR s1, s2;
82*aef9bcd9SKiyoung Kim 
83*aef9bcd9SKiyoung Kim     s1 = s2 = _scalar(0.0);
84*aef9bcd9SKiyoung Kim     for (isp = 0; isp < nsp; isp++) {
85*aef9bcd9SKiyoung Kim         s1 += (SCALAR)isp * *p_spec;
86*aef9bcd9SKiyoung Kim         s2 += *p_spec++;
87*aef9bcd9SKiyoung Kim     }
88*aef9bcd9SKiyoung Kim 
89*aef9bcd9SKiyoung Kim     if (s2 < LDAC_TH_ZERODIV) {
90*aef9bcd9SKiyoung Kim         centroid = _scalar(0.0);
91*aef9bcd9SKiyoung Kim     }
92*aef9bcd9SKiyoung Kim     else {
93*aef9bcd9SKiyoung Kim         centroid = s1 / s2;
94*aef9bcd9SKiyoung Kim     }
95*aef9bcd9SKiyoung Kim 
96*aef9bcd9SKiyoung Kim     return centroid;
97*aef9bcd9SKiyoung Kim }
98*aef9bcd9SKiyoung Kim 
99*aef9bcd9SKiyoung Kim /***************************************************************************************************
100*aef9bcd9SKiyoung Kim     Calculate Number of Zero Cross
101*aef9bcd9SKiyoung Kim ***************************************************************************************************/
calc_zero_cross_number_ldac(SCALAR * p_time,int n)102*aef9bcd9SKiyoung Kim static int calc_zero_cross_number_ldac(
103*aef9bcd9SKiyoung Kim SCALAR *p_time,
104*aef9bcd9SKiyoung Kim int n)
105*aef9bcd9SKiyoung Kim {
106*aef9bcd9SKiyoung Kim     int i;
107*aef9bcd9SKiyoung Kim     int zero_cross = 0;
108*aef9bcd9SKiyoung Kim     SCALAR prev;
109*aef9bcd9SKiyoung Kim 
110*aef9bcd9SKiyoung Kim     prev = _scalar(0.0);
111*aef9bcd9SKiyoung Kim     for (i = 0; i < n; i++) {
112*aef9bcd9SKiyoung Kim         if (prev * *p_time < _scalar(0.0)) {
113*aef9bcd9SKiyoung Kim             zero_cross++;
114*aef9bcd9SKiyoung Kim         }
115*aef9bcd9SKiyoung Kim         prev = *p_time++;
116*aef9bcd9SKiyoung Kim     }
117*aef9bcd9SKiyoung Kim 
118*aef9bcd9SKiyoung Kim     return zero_cross;
119*aef9bcd9SKiyoung Kim }
120*aef9bcd9SKiyoung Kim 
121*aef9bcd9SKiyoung Kim /***************************************************************************************************
122*aef9bcd9SKiyoung Kim     Analyze Frame Status
123*aef9bcd9SKiyoung Kim ***************************************************************************************************/
ana_frame_status_ldac(SFINFO * p_sfinfo,int nlnn)124*aef9bcd9SKiyoung Kim DECLSPEC int ana_frame_status_ldac(
125*aef9bcd9SKiyoung Kim SFINFO *p_sfinfo,
126*aef9bcd9SKiyoung Kim int nlnn)
127*aef9bcd9SKiyoung Kim {
128*aef9bcd9SKiyoung Kim     AC *p_ac;
129*aef9bcd9SKiyoung Kim     int ich;
130*aef9bcd9SKiyoung Kim     int nchs = p_sfinfo->cfg.ch;
131*aef9bcd9SKiyoung Kim     int nsmpl = npow2_ldac(nlnn+1);
132*aef9bcd9SKiyoung Kim     int cnt, zero_cross;
133*aef9bcd9SKiyoung Kim     int a_status[LDAC_PRCNCH];
134*aef9bcd9SKiyoung Kim     SCALAR low_energy, centroid;
135*aef9bcd9SKiyoung Kim     SCALAR a_psd_spec[LDAC_NSP_PSEUDOANA];
136*aef9bcd9SKiyoung Kim 
137*aef9bcd9SKiyoung Kim     for (ich = 0; ich < nchs; ich++) {
138*aef9bcd9SKiyoung Kim         p_ac = p_sfinfo->ap_ac[ich];
139*aef9bcd9SKiyoung Kim 
140*aef9bcd9SKiyoung Kim         low_energy = calc_mdct_pseudo_spectrum_ldac(p_ac->p_acsub->a_spec, a_psd_spec, LDAC_NSP_PSEUDOANA);
141*aef9bcd9SKiyoung Kim 
142*aef9bcd9SKiyoung Kim         centroid = calc_spectral_centroid_ldac(a_psd_spec, LDAC_NSP_PSEUDOANA);
143*aef9bcd9SKiyoung Kim 
144*aef9bcd9SKiyoung Kim         zero_cross = calc_zero_cross_number_ldac(p_ac->p_acsub->a_time, nsmpl);
145*aef9bcd9SKiyoung Kim 
146*aef9bcd9SKiyoung Kim         a_status[ich] = LDAC_FRMSTAT_LEV_0;
147*aef9bcd9SKiyoung Kim         if (low_energy < LDAC_TH_LOWENERGY_L) {
148*aef9bcd9SKiyoung Kim             a_status[ich] = LDAC_FRMSTAT_LEV_3;
149*aef9bcd9SKiyoung Kim         }
150*aef9bcd9SKiyoung Kim         else {
151*aef9bcd9SKiyoung Kim             if (low_energy < LDAC_TH_LOWENERGY_M) {
152*aef9bcd9SKiyoung Kim                 a_status[ich] = LDAC_FRMSTAT_LEV_2;
153*aef9bcd9SKiyoung Kim             }
154*aef9bcd9SKiyoung Kim             else if (low_energy < LDAC_TH_LOWENERGY_H) {
155*aef9bcd9SKiyoung Kim                 a_status[ich] = LDAC_FRMSTAT_LEV_1;
156*aef9bcd9SKiyoung Kim             }
157*aef9bcd9SKiyoung Kim 
158*aef9bcd9SKiyoung Kim             cnt = p_ac->frmana_cnt;
159*aef9bcd9SKiyoung Kim             if ((centroid > LDAC_TH_CENTROID) && (zero_cross >= LDAC_TH_ZCROSNUM)) {
160*aef9bcd9SKiyoung Kim                 cnt++;
161*aef9bcd9SKiyoung Kim 
162*aef9bcd9SKiyoung Kim                 if (cnt >= LDAC_MAXCNT_FRMANA) {
163*aef9bcd9SKiyoung Kim                     cnt = LDAC_MAXCNT_FRMANA;
164*aef9bcd9SKiyoung Kim                     a_status[ich] = LDAC_FRMSTAT_LEV_2;
165*aef9bcd9SKiyoung Kim                 }
166*aef9bcd9SKiyoung Kim                 else if (a_status[ich] <= LDAC_FRMSTAT_LEV_1) {
167*aef9bcd9SKiyoung Kim                     a_status[ich]++;
168*aef9bcd9SKiyoung Kim                 }
169*aef9bcd9SKiyoung Kim             }
170*aef9bcd9SKiyoung Kim             else {
171*aef9bcd9SKiyoung Kim                 cnt = 0;
172*aef9bcd9SKiyoung Kim             }
173*aef9bcd9SKiyoung Kim             p_ac->frmana_cnt = cnt;
174*aef9bcd9SKiyoung Kim         }
175*aef9bcd9SKiyoung Kim     }
176*aef9bcd9SKiyoung Kim 
177*aef9bcd9SKiyoung Kim     if (nchs == LDAC_CHANNEL_1CH) {
178*aef9bcd9SKiyoung Kim         return a_status[0];
179*aef9bcd9SKiyoung Kim     }
180*aef9bcd9SKiyoung Kim     else {
181*aef9bcd9SKiyoung Kim         return min_ldac(a_status[0], a_status[1]);
182*aef9bcd9SKiyoung Kim     }
183*aef9bcd9SKiyoung Kim }
184*aef9bcd9SKiyoung Kim 
185