www.pudn.com > AVS_M_ver10.rar > dec_tcx_stereo.c
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2007 Audio Video Coding Standard, Part ¢ú
*
* This software module was developed by AVS Audio sub-group
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the users without any
* license fee or royalty on an "as is" basis. The AVS disclaims
* any and all warranties, whether express, implied, or statutory,
* including any implied warranties of merchantability or of fitness
* for a particular purpose. In no event shall the contributors or
* the AVS be liable for any incidental, punitive, or consequential
* damages of any kind whatsoever arising from the use of this program.
*
* This disclaimer of warranty extends to the user of this program
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The AVS does not represent or warrant that the program furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy is available from the AVS Web site at
* http://www.avs.org.cn
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
************************************************************************
*/
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "../include/amr_plus.h"
/* prototypes*/
void dec_prm_tcx_stereo(int mod[], /* (i) : frame mode (mode[4], 4 division) */
int param[], /* (i) : parameters */
short serial[], /* (o) : serial bits stream */
int nbits);
void init_tcx_stereo_decoder(Decoder_State_Plus *st)
{
st->mem_stereo_ovlp_size = 0;
set_zero(st->mem_stereo_ovlp,L_OVLP_2k);
st->mem_balance = 0;
}
float d_balance( /* output: gain */
int index /* (i) : index */
)
{
float balance = (float) index / 32.0f - 2.0f;
return(balance);
}
void dtcx_stereo(float synth[], /* in/out: synth[-M..lg] */
float mono[],
float wovlp[], /* i/o: wovlp[0..127] */
int ovlp_size, /* input: 0, 64 or 128 (0=acelp) */
int L_frame, /* input: frame length */
int prm[],
int pre_echo,
int bad_frame[],
Decoder_State_Plus *st)
{
int i, k, i_subfr, lg;
float tmp, gain;
int any_bad_frame;
float xri[L_TCX_LB];
float *xnq=xri;
float wm_arr[L_TCX_LB+ECU_WIEN_ORD];
float window[32+32];
float *wm = &amt;wm_arr[ECU_WIEN_ORD];
float balance;
float gain_shap[8];
float rmm[ECU_WIEN_ORD+1];
float rms[ECU_WIEN_ORD+1];
float *h;
int lext=32;
int n_pack = 4;
/*------ set length of overlap (lext) and length of encoded frame (lg) -----*/
for (i=0;i< ECU_WIEN_ORD;i++) {
wm_arr[i] = 0;
}
h = st->h;
switch (L_frame) {
case 40:
lext = 8;
n_pack=1;
break;
case 80:
lext = 16;
n_pack =2;
break;
case 160:
lext = 32;
n_pack= 4;
break;
};
lg = L_frame + lext;
any_bad_frame = 0;
for (i=0; i<n_pack; i++)
{
any_bad_frame |= bad_frame[i];
}
/* built window for overlaps section */
cos_window(window, ovlp_size, lext);
/* these are already concealed by the avq demux */
for(i=0; i<lg; i++)
{
xri[i] = (float)prm[i+2];
}
/* only in mode 0,1 */
/* windowed mono */
for (i=0; i<lg; i++){
wm[i] = mono[i];
}
/* windowing for TCX overlap and correlation */
for (i=0; i<ovlp_size; i++)
{
wm[i] *= window[i];
}
for (i=0; i<lext; i++) {
wm[L_frame+i] *= window[ovlp_size+i];
}
if(pre_echo){
/* compensate for the gain */
tmp = 0.0f;
for(i=0;i<lg;i+=16){
gain_shap[i/16] = 0.001f;
for(k=0;k<16;k++)
{
gain_shap[i/16] += wm[i+k]*wm[i+k];
}
/* average log gain in frame */
tmp += (float)log10(gain_shap[i/16]);
}
tmp /= (float)(lg/16);
for(i=0;i<lg/16;i++){
gain_shap[i] = (float)sqrt(gain_shap[i]*pow(10.0f,-tmp));
gain_shap[i] = my_min(2.0,my_max(0.5,gain_shap[i]));
}
}
/*-----------------------------------------------------------*
* Compute inverse FFT for obtaining xnq[] without noise. *
* Coefficients (xri[]) order are *
* re[0], re[n/2], re[1], re[2], ... re[n/2-1], im[n/2-1] *
* Note that last FFT element (re[n/2]) is zeroed. *
*-----------------------------------------------------------*/
#ifdef NEW_TVC
adap_pulse_deemph(xri,4*lg);
#else
adap_low_freq_deemph(xri,4*lg);
#endif
xri[1]=0.0f;
ifft3(xri, xnq, (short)lg);
tmp = 1.0f;
if (bad_frame[0]){
/* if this was predictive we could have a work around */
balance = (float)(0.9*st->mem_balance);
st->mem_balance = balance;
}
else {
/* balance is safe */
balance = d_balance(prm[0]);
st->mem_balance = balance;
}
if (pre_echo) {
for(i=0;i<lg;i+=16){
for(k=0;k<16;k++)
{
xnq[i+k] *= gain_shap[i/16];
}
}
}
gain = d_gain_tcx(prm[1], xnq, lg, any_bad_frame, &amt;(st->side_rms));
if (L_frame!=40 || bad_frame[0]==0) {
for(i=0; i<lg; i++) {
xnq[i] = gain * xnq[i] + balance* wm[i];
}
}
else {
for(i=0;i<lg;i++)
{
xnq[i] = 0;
for (k=0;k<ECU_WIEN_ORD+1;k++) {
xnq[i] += h[k] * wm[i-k];
}
}
}
if (!any_bad_frame) {
/* Create rmm and rms */
crosscorr(wm,wm,rmm,lg,0,ECU_WIEN_ORD+1);
crosscorr(xnq,wm,rms,lg,0,ECU_WIEN_ORD+1);
glev_s(h,rmm,rms,ECU_WIEN_ORD+1);
}
/*-----------------------------------------------------------*
* find and quantize gain, multiply xnq[] by gain. *
* windowing of xnq[] for TCX overlap. *
*-----------------------------------------------------------*/
/* adaptive windowing on overlap (beginning and end of frame) */
for (i=0; i<ovlp_size; i++)
{
xnq[i] *= window[i];
}
for (i=0; i<lext; i++)
{
xnq[i+L_frame] *= window[ovlp_size+i];
}
for (i=L_frame+lext; i<lg; i++)
{
xnq[i] = 0;
}
/*-----------------------------------------------------------*
* TCX overlap and add. Update memory for next overlap. *
*-----------------------------------------------------------*/
for (i=0; i<L_OVLP_2k; i++)
{
xnq[i] += wovlp[i];
}
/* save overlap for next frame */
for (i=0; i<lext; i++)
{
wovlp[i] = xnq[i+L_frame];
}
for (i=lext; i<L_OVLP_2k; i++)
{
wovlp[i] = 0.0;
}
/*-----------------------------------------------------------*
* find excitation and synthesis *
*-----------------------------------------------------------*/
for (i_subfr=0; i_subfr<L_frame; i_subfr++)
{
synth[i_subfr] = xnq[i_subfr];
}
return;
}
/*-----------------------------------------------------------------*
* Funtion dec_tcx_stereo *
* ~~~~~~~~~~~~~~~~~~~~ *
*-----------------------------------------------------------------*/
void dec_tcx_stereo(float synth_2k[],
float left_2k[],
float right_2k[],
int param[],
int bad_frame[],
Decoder_State_Plus *st)
{
float synth_side[L_FRAME_2k];
/* Scalars */
int i,k, mod[4];
int bfi;
int *prm;
bfi = bad_frame[0] || bad_frame[1] || bad_frame[2] || bad_frame[3];
/* get the mode */
for(k=0;k<4;k++)
{
mod[k] = param[k];
}
/* tcx decoder loop */
k = 0;
while (k < NB_DIV)
{
prm = param+ 4 + (k*NPRM_DIV_TCX_STEREO);
if (mod[k] == 1 || mod[k] == 0) {
dtcx_stereo(
&amt;synth_side[k*L_DIV_2k],
&amt;synth_2k[k*L_DIV_2k],
st->mem_stereo_ovlp,
st->mem_stereo_ovlp_size,
L_FRAME_2k/4,
prm,
!mod[k],
bad_frame+k,
st);
st->mem_stereo_ovlp_size = L_OVLP_2k/4;
k++;
} else if (mod[k] == 2) {
dtcx_stereo(
&amt;synth_side[k*L_DIV_2k],
&amt;synth_2k[k*L_DIV_2k],
st->mem_stereo_ovlp,
st->mem_stereo_ovlp_size,
L_FRAME_2k/2,
prm,0,
bad_frame+k,
st);
st->mem_stereo_ovlp_size = L_OVLP_2k/2;
k+=2;
} else if(mod[k] == 3) {
dtcx_stereo(
&amt;synth_side[k*L_DIV_2k],
&amt;synth_2k[k*L_DIV_2k],
st->mem_stereo_ovlp,
st->mem_stereo_ovlp_size,
L_FRAME_2k,
prm,
0,
bad_frame+k,
st);
st->mem_stereo_ovlp_size = L_OVLP_2k;
k+=4;
} else {
printf("\n error, unknown mode");
exit(-1);
}
}
k=0;
while(k<NB_DIV)
{
if(mod[k]==0 || mod[k] ==1)
{
for(i=k*L_FRAME_2k/4;i<k*L_FRAME_2k/4+L_FRAME_2k/4;i++)
{
left_2k[i] = synth_2k[i] + synth_side[i];
right_2k[i] = synth_2k[i] - synth_side[i];
}
k++;
}
else if(mod[k] ==2)
{
for(i=k*L_FRAME_2k/4;i<k*L_FRAME_2k/4+L_FRAME_2k/2;i++)
{
left_2k[i] = synth_2k[i] + synth_side[i];
right_2k[i] = synth_2k[i] - synth_side[i];
}
k+=2;
}
else
{
for(i=0;i<L_FRAME_2k;i++)
{
left_2k[i] = synth_2k[i] + synth_side[i];
right_2k[i] = synth_2k[i] - synth_side[i];
}
k+=4;
}
}
return;
}