Home | History | Annotate | Download | only in src
      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_Q_LOWENERGY    11
     21 #define LDAC_Q_ADD_LOWENERGY 4
     22 
     23 #define LDAC_TH_LOWENERGY_L (0x070bc28f>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(225.47)(Q19)>>4 */
     24 #define LDAC_TH_LOWENERGY_M (0x1c0ce148>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(897.61)(Q19)>>4 */
     25 #define LDAC_TH_LOWENERGY_H (0x6fab851f>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(3573.44)(Q19)>>4 */
     26 
     27 #define LDAC_TH_CENTROID 0x00168000 /* Q15, _scalar(45.0) */
     28 
     29 /***************************************************************************************************
     30     Lookup Table for Calculating Square Root Value
     31 ***************************************************************************************************/
     32 static INT16 sa_sqrt_ldac[97] = { /* Q14 */
     33     0x2d41, 0x2df4, 0x2ea5, 0x2f54, 0x3000, 0x30a9, 0x3150, 0x31f5,
     34     0x3298, 0x3339, 0x33d8, 0x3475, 0x3510, 0x35aa, 0x3642, 0x36d8,
     35     0x376c, 0x3800, 0x3891, 0x3921, 0x39b0, 0x3a3d, 0x3ac9, 0x3b54,
     36     0x3bdd, 0x3c66, 0x3ced, 0x3d72, 0x3df7, 0x3e7b, 0x3efd, 0x3f7f,
     37     0x4000, 0x407f, 0x40fe, 0x417b, 0x41f8, 0x4273, 0x42ee, 0x4368,
     38     0x43e1, 0x445a, 0x44d1, 0x4548, 0x45be, 0x4633, 0x46a7, 0x471b,
     39     0x478d, 0x4800, 0x4871, 0x48e2, 0x4952, 0x49c1, 0x4a30, 0x4a9e,
     40     0x4b0b, 0x4b78, 0x4be5, 0x4c50, 0x4cbb, 0x4d26, 0x4d90, 0x4df9,
     41     0x4e62, 0x4eca, 0x4f32, 0x4f99, 0x5000, 0x5066, 0x50cb, 0x5130,
     42     0x5195, 0x51f9, 0x525d, 0x52c0, 0x5323, 0x5385, 0x53e7, 0x5449,
     43     0x54a9, 0x550a, 0x556a, 0x55ca, 0x5629, 0x5688, 0x56e6, 0x5745,
     44     0x57a2, 0x5800, 0x585c, 0x58b9, 0x5915, 0x5971, 0x59cc, 0x5a27,
     45     0x5a82,
     46 };
     47 
     48 /***************************************************************************************************
     49     Subfunction: Multiply
     50 ***************************************************************************************************/
     51 __inline static INT32 mul_ldac(
     52 INT32 in1,
     53 INT32 in2)
     54 {
     55     INT32 out;
     56     INT64 acc;
     57 
     58     /* Q30 <- Q30 * Q30 */
     59     acc = (INT64)in1 * in2;
     60     acc >>= 30;
     61 
     62     if (acc > LDAC_MAX_32BIT) {
     63         out = LDAC_MAX_32BIT;
     64     }
     65     else if (acc < LDAC_MIN_32BIT) {
     66         out = LDAC_MIN_32BIT;
     67     }
     68     else {
     69         out = (INT32)acc;
     70     }
     71 
     72     return out;
     73 }
     74 
     75 /***************************************************************************************************
     76     Subfunction: Subtract
     77 ***************************************************************************************************/
     78 __inline static INT32 sub_ldac(
     79 INT32 in1,
     80 INT32 in2)
     81 {
     82     INT32 out;
     83 
     84     out = in1 - in2;
     85 
     86     return out;
     87 }
     88 
     89 /***************************************************************************************************
     90     Subfunction: Add
     91 ***************************************************************************************************/
     92 __inline static INT32 add_ldac(
     93 INT32 in1,
     94 INT32 in2)
     95 {
     96     INT32 out;
     97 
     98     out = in1 + in2;
     99 
    100     return out;
    101 }
    102 
    103 /***************************************************************************************************
    104     Subfunction: Multiply and Add
    105 ***************************************************************************************************/
    106 __inline static INT32 mad_ldac(
    107 INT32 in1,
    108 INT32 in2,
    109 INT32 in3)
    110 {
    111     INT32 out;
    112 
    113     out = mul_ldac(in2, in3);
    114     out = add_ldac(in1, out);
    115 
    116     return out;
    117 }
    118 
    119 /***************************************************************************************************
    120     Subfunction: Normalize
    121 ***************************************************************************************************/
    122 __inline static INT16 norm_ldac(
    123 UINT32 val)
    124 {
    125     INT16 len;
    126 
    127     len = 0;
    128     while (val > 0) {
    129         val >>= 1;
    130         len++;
    131     }
    132 
    133     return len;
    134 }
    135 
    136 /***************************************************************************************************
    137     Subfunction: Calculate Exponential
    138 ***************************************************************************************************/
    139 __inline static INT16 calc_exp_ldac(
    140 INT32 in_h,
    141 UINT32 in_l)
    142 {
    143     INT16 e;
    144 
    145     if (in_h) {
    146         e = norm_ldac((UINT32)in_h) + 32;
    147     }
    148     else {
    149         e = norm_ldac(in_l);
    150     }
    151     e = (63 - e) & 0xfffe;
    152 
    153     return e;
    154 }
    155 
    156 /***************************************************************************************************
    157     Subfunction: Calculate Square Root
    158 ***************************************************************************************************/
    159 __inline static INT32 calc_sqrt_ldac(
    160 INT32 in,
    161 INT16 e)
    162 {
    163     INT16 i;
    164     INT32 val, dif, a;
    165 
    166     if (in <= 0) {
    167         return 0;
    168     }
    169 
    170     i = (INT16)(in >> 24);
    171     a = in & 0x00ffffffL;
    172 
    173     i = i - 32;
    174     val = sa_sqrt_ldac[i] << 16; /* Q30 <- Q14 << 16 */
    175     dif = sub_ldac(sa_sqrt_ldac[i+1]<<16, val); /* Q30 */
    176     a = (INT32)(((INT64)a << 30) >> 24); /* Q30 a = a / 0x1000000 */
    177     val = mad_ldac(val, dif, a);
    178     val = val >> (e >> 1);
    179 
    180     return val;
    181 }
    182 
    183 /***************************************************************************************************
    184     Calculate Pseudo Spectrum and Low Band Energy
    185 ***************************************************************************************************/
    186 static INT32 calc_mdct_pseudo_spectrum_ldac(
    187 INT32 *p_spec,
    188 INT32 *p_psd,
    189 UINT32 nsp)
    190 {
    191     UINT32 isp;
    192     INT16 e;
    193     INT32 y0, y1, y2;
    194     INT32 tmp;
    195     INT64 low_energy;
    196     INT64 acc1, acc2;
    197 
    198     {
    199         y1 = p_spec[0];
    200         y2 = p_spec[1];
    201         acc1 = (INT64)y1 * (INT64)y1;
    202         acc2 = (INT64)y2 * (INT64)y2;
    203         acc1 = acc1 + acc2;
    204         low_energy = acc1 >> LDAC_Q_ADD_LOWENERGY; /* Q26 <- (Q15 * Q15) >> 4 */
    205         e = calc_exp_ldac((INT32)(acc1>>32), (UINT32)(acc1&0xffffffff));
    206         tmp = (INT32)((acc1 << e) >> 32);
    207         *p_psd++ = calc_sqrt_ldac(tmp, e);
    208     }
    209 
    210     for (isp = 1; isp < LDAC_NSP_LOWENERGY; isp++) {
    211         y0 = y1;
    212         y1 = y2;
    213         y2 = p_spec[isp+1];
    214         acc1 = (INT64)y1 * (INT64)y1;
    215         acc2 = (INT64)(y0-y2) * (INT64)(y0-y2);
    216         acc1 = acc1 + acc2;
    217         low_energy += acc1 >> LDAC_Q_ADD_LOWENERGY; /* Q26 <- (Q15 * Q15) >> 4 */
    218         e = calc_exp_ldac((INT32)(acc1>>32), (UINT32)(acc1&0xffffffff));
    219         tmp = (INT32)((acc1 << e) >> 32);
    220         *p_psd++ = calc_sqrt_ldac(tmp, e);
    221     }
    222 
    223     for (isp = LDAC_NSP_LOWENERGY; isp < nsp-1; isp++) {
    224         y0 = y1;
    225         y1 = y2;
    226         y2 = p_spec[isp+1];
    227         acc1 = (INT64)y1 * (INT64)y1;
    228         acc2 = (INT64)(y0-y2) * (INT64)(y0-y2);
    229         acc1 = acc1 + acc2;
    230         e = calc_exp_ldac((INT32)(acc1 >> 32), (UINT32)(acc1&0xffffffff));
    231         tmp = (INT32) ((acc1 << e) >> 32);
    232         *p_psd++ = calc_sqrt_ldac(tmp, e);
    233     }
    234 
    235     {
    236         acc1 = (INT64)y1 * (INT64)y1;
    237         acc2 = (INT64)y2 * (INT64)y2;
    238         acc1 = acc1 + acc2;
    239         e = calc_exp_ldac((INT32)(acc1 >> 32), (UINT32)(acc1&0xffffffff));
    240         tmp = (INT32)((acc1 << e) >> 32);
    241         *p_psd++ = calc_sqrt_ldac(tmp, e);
    242     }
    243 
    244     low_energy >>= LDAC_Q_LOWENERGY; /* Q15 <- Q26 >> 11 */
    245     if (low_energy > LDAC_MAX_32BIT) {
    246         low_energy = LDAC_MAX_32BIT;
    247     }
    248 
    249     return (INT32)low_energy;
    250 }
    251 
    252 /***************************************************************************************************
    253     Calculate Pseudo Spectrum Centroid
    254 ***************************************************************************************************/
    255 static INT32 calc_spectral_centroid_ldac(
    256 INT32 *p_spec,
    257 UINT32 nsp)
    258 {
    259     UINT32 isp;
    260     INT32 centroid = 0;
    261     INT64 s1, s2;
    262 
    263     s1 = s2 = 0;
    264     for (isp = 0; isp < nsp; isp++) {
    265         s1 += ((INT64)isp * (INT64)*p_spec); /* Q15 <- Q00 * Q15 */
    266         s2 += (INT64)*p_spec++; /* Q15 */
    267     }
    268 
    269     if (s2 != 0) {
    270         centroid = (INT32)((s1<<15) / s2); /* Q15 <- (Q15<<15) / Q15 */
    271     }
    272 
    273     return centroid;
    274 }
    275 
    276 /***************************************************************************************************
    277     Calculate Number of Zero Cross
    278 ***************************************************************************************************/
    279 static UINT32 calc_zero_cross_number_ldac(
    280 INT32 *p_time,
    281 UINT32 n)
    282 {
    283     UINT32 i;
    284     UINT32 zero_cross = 0;
    285     INT32 prev, tmp;
    286 
    287     prev = 0;
    288     for (i = 0; i < n; i++) {
    289         if ((prev == 0) || (*p_time == 0)) {
    290             tmp = 0;
    291         }
    292         else {
    293             tmp = prev ^ (*p_time);
    294         }
    295 
    296         if (tmp < 0) {
    297             zero_cross++;
    298         }
    299         prev = *p_time++;
    300     }
    301 
    302     return zero_cross;
    303 }
    304 
    305 /***************************************************************************************************
    306     Analyze Frame Status
    307 ***************************************************************************************************/
    308 DECLSPEC int ana_frame_status_ldac(
    309 SFINFO *p_sfinfo,
    310 int nlnn)
    311 {
    312     AC *p_ac;
    313     int ich;
    314     int nchs = p_sfinfo->cfg.ch;
    315     int nsmpl = npow2_ldac(nlnn+1);
    316     int cnt;
    317     int a_status[LDAC_PRCNCH];
    318     UINT32 zero_cross;
    319     INT32 low_energy, centroid;
    320     INT32 a_psd_spec[LDAC_NSP_PSEUDOANA];
    321 
    322 
    323     for (ich = 0; ich < nchs; ich++) {
    324         p_ac = p_sfinfo->ap_ac[ich];
    325 
    326         low_energy = calc_mdct_pseudo_spectrum_ldac(p_ac->p_acsub->a_spec, a_psd_spec, LDAC_NSP_PSEUDOANA);
    327 
    328         centroid = calc_spectral_centroid_ldac(a_psd_spec, LDAC_NSP_PSEUDOANA);
    329 
    330         zero_cross = calc_zero_cross_number_ldac(p_ac->p_acsub->a_time, nsmpl);
    331 
    332         a_status[ich] = LDAC_FRMSTAT_LEV_0;
    333         if (low_energy < LDAC_TH_LOWENERGY_L) {
    334             a_status[ich] = LDAC_FRMSTAT_LEV_3;
    335         }
    336         else {
    337             if (low_energy < LDAC_TH_LOWENERGY_M) {
    338                 a_status[ich] = LDAC_FRMSTAT_LEV_2;
    339             }
    340             else if (low_energy < LDAC_TH_LOWENERGY_H) {
    341                 a_status[ich] = LDAC_FRMSTAT_LEV_1;
    342             }
    343 
    344             cnt = p_ac->frmana_cnt;
    345             if ((centroid > LDAC_TH_CENTROID) && (zero_cross >= LDAC_TH_ZCROSNUM)) {
    346                 cnt++;
    347 
    348                 if (cnt >= LDAC_MAXCNT_FRMANA) {
    349                     cnt = LDAC_MAXCNT_FRMANA;
    350                     a_status[ich] = LDAC_FRMSTAT_LEV_2;
    351                 }
    352                 else if (a_status[ich] <= LDAC_FRMSTAT_LEV_1) {
    353                     a_status[ich]++;
    354                 }
    355             }
    356             else {
    357                 cnt = 0;
    358             }
    359             p_ac->frmana_cnt = cnt;
    360         }
    361     }
    362 
    363     if (nchs == LDAC_CHANNEL_1CH) {
    364         return a_status[0];
    365     } else {
    366         return min_ldac(a_status[0], a_status[1]);
    367     }
    368 }
    369 
    370