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