/*
|
* Copyright (C) 2003 - 2016 Sony Corporation
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#include "ldac.h"
|
|
|
#define LDAC_TH_LOWENERGY_L _scalar(225.47)
|
#define LDAC_TH_LOWENERGY_M _scalar(897.61)
|
#define LDAC_TH_LOWENERGY_H _scalar(3573.44)
|
|
#define LDAC_TH_CENTROID _scalar(45.0)
|
#define LDAC_TH_ZERODIV _scalar(1.0e-6)
|
|
/***************************************************************************************************
|
Calculate Pseudo Spectrum and Low Band Energy
|
***************************************************************************************************/
|
static SCALAR calc_mdct_pseudo_spectrum_ldac(
|
SCALAR *p_spec,
|
SCALAR *p_psd,
|
int n)
|
{
|
int isp;
|
SCALAR low_energy, tmp;
|
SCALAR y0, y1, y2;
|
|
{
|
y1 = p_spec[0];
|
y2 = p_spec[1];
|
tmp = y1 * y1 + y2 * y2;
|
low_energy = tmp;
|
p_psd[0] = sqrt(tmp);
|
}
|
|
for (isp = 1; isp < LDAC_NSP_LOWENERGY; isp++) {
|
y0 = y1;
|
y1 = y2;
|
y2 = p_spec[isp+1];
|
tmp = y1 * y1 + (y0-y2) * (y0-y2);
|
low_energy += tmp;
|
p_psd[isp] = sqrt(tmp);
|
}
|
|
for (isp = LDAC_NSP_LOWENERGY; isp < n-1; isp++) {
|
y0 = y1;
|
y1 = y2;
|
y2 = p_spec[isp+1];
|
tmp = y1 * y1 + (y0-y2) * (y0-y2);
|
p_psd[isp] = sqrt(tmp);
|
}
|
|
{
|
tmp = y1 * y1 + y2 * y2;
|
p_psd[n-1] = sqrt(tmp);
|
}
|
|
return low_energy;
|
}
|
|
/***************************************************************************************************
|
Calculate Pseudo Spectrum Centroid
|
***************************************************************************************************/
|
static SCALAR calc_spectral_centroid_ldac(
|
SCALAR *p_spec,
|
int nsp)
|
{
|
int isp;
|
SCALAR centroid;
|
SCALAR s1, s2;
|
|
s1 = s2 = _scalar(0.0);
|
for (isp = 0; isp < nsp; isp++) {
|
s1 += (SCALAR)isp * *p_spec;
|
s2 += *p_spec++;
|
}
|
|
if (s2 < LDAC_TH_ZERODIV) {
|
centroid = _scalar(0.0);
|
}
|
else {
|
centroid = s1 / s2;
|
}
|
|
return centroid;
|
}
|
|
/***************************************************************************************************
|
Calculate Number of Zero Cross
|
***************************************************************************************************/
|
static int calc_zero_cross_number_ldac(
|
SCALAR *p_time,
|
int n)
|
{
|
int i;
|
int zero_cross = 0;
|
SCALAR prev;
|
|
prev = _scalar(0.0);
|
for (i = 0; i < n; i++) {
|
if (prev * *p_time < _scalar(0.0)) {
|
zero_cross++;
|
}
|
prev = *p_time++;
|
}
|
|
return zero_cross;
|
}
|
|
/***************************************************************************************************
|
Analyze Frame Status
|
***************************************************************************************************/
|
DECLSPEC int ana_frame_status_ldac(
|
SFINFO *p_sfinfo,
|
int nlnn)
|
{
|
AC *p_ac;
|
int ich;
|
int nchs = p_sfinfo->cfg.ch;
|
int nsmpl = npow2_ldac(nlnn+1);
|
int cnt, zero_cross;
|
int a_status[LDAC_PRCNCH];
|
SCALAR low_energy, centroid;
|
SCALAR a_psd_spec[LDAC_NSP_PSEUDOANA];
|
|
for (ich = 0; ich < nchs; ich++) {
|
p_ac = p_sfinfo->ap_ac[ich];
|
|
low_energy = calc_mdct_pseudo_spectrum_ldac(p_ac->p_acsub->a_spec, a_psd_spec, LDAC_NSP_PSEUDOANA);
|
|
centroid = calc_spectral_centroid_ldac(a_psd_spec, LDAC_NSP_PSEUDOANA);
|
|
zero_cross = calc_zero_cross_number_ldac(p_ac->p_acsub->a_time, nsmpl);
|
|
a_status[ich] = LDAC_FRMSTAT_LEV_0;
|
if (low_energy < LDAC_TH_LOWENERGY_L) {
|
a_status[ich] = LDAC_FRMSTAT_LEV_3;
|
}
|
else {
|
if (low_energy < LDAC_TH_LOWENERGY_M) {
|
a_status[ich] = LDAC_FRMSTAT_LEV_2;
|
}
|
else if (low_energy < LDAC_TH_LOWENERGY_H) {
|
a_status[ich] = LDAC_FRMSTAT_LEV_1;
|
}
|
|
cnt = p_ac->frmana_cnt;
|
if ((centroid > LDAC_TH_CENTROID) && (zero_cross >= LDAC_TH_ZCROSNUM)) {
|
cnt++;
|
|
if (cnt >= LDAC_MAXCNT_FRMANA) {
|
cnt = LDAC_MAXCNT_FRMANA;
|
a_status[ich] = LDAC_FRMSTAT_LEV_2;
|
}
|
else if (a_status[ich] <= LDAC_FRMSTAT_LEV_1) {
|
a_status[ich]++;
|
}
|
}
|
else {
|
cnt = 0;
|
}
|
p_ac->frmana_cnt = cnt;
|
}
|
}
|
|
if (nchs == LDAC_CHANNEL_1CH) {
|
return a_status[0];
|
}
|
else {
|
return min_ldac(a_status[0], a_status[1]);
|
}
|
}
|