www.pudn.com > AVS_M_ver10.rar > dec_tcx.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"
/* local function */

static int find_mpitch(float xri[], int lg);
#ifdef NEW_TVC
float ol_synth[1024+16];
#endif
void decoder_tcx(
int prm[], /* input: parameters */
int nbits_AVQ[], /* input: nbits in parameters of AVQ */
float A[], /* input: coefficients NxAz[M+1] */
int L_frame, /* input: frame length */
int bad_frame[], /* input: Bad frame indicator */
float exc[], /* output: exc[-lg..lg] */
float synth[], /* in/out: synth[-M..lg] */
Decoder_State_Plus *st) /* i/o : coder memory state */
{
#ifdef PW_UPDATE
float mem_temp1[M],mem_temp2[TILT_ORDER];
#endif

#ifdef NEW_TVC
int i, k, i_subfr, index, index2, lg, lext, bfi, n_pack, tmp2;
float tmp, gain, fac_ns,tmp1;
float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1];
float oldsynth[16];
float *xri, *xnq;
float window[128+128];
float gband;
int any_loss,num_loss;
#else
int i, k, i_subfr, index, lg, lext, bfi, n_pack;
float tmp, gain, fac_ns;
float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1];
float *xri, *xnq;
float window[128+128];
int any_loss,num_loss;
#endif
xri = exc;
xnq = synth;
if (L_frame == (L_FRAME_PLUS/4)) {
n_pack = 1;
} else if (L_frame == (L_FRAME_PLUS/2)) {
n_pack = 2;
} else if (L_frame == (L_FRAME_PLUS)) {
n_pack = 4;
} else {
printf( "decoder_tcx: Invalid L_frame, exiting\n" );
exit(1);
}
any_loss = 0;
num_loss = 0;
for (i=0; i<n_pack; i++) {
any_loss |= bad_frame[i];
num_loss += bad_frame[i];
}
/*------ set length of overlap (lext) and length of encoded frame (lg) -----*/
lext = L_OVLP;
if (L_frame == (L_FRAME_PLUS/2)) {
lext = L_OVLP/2;
} else if (L_frame == (L_FRAME_PLUS/4)) {
lext = L_OVLP/4;
}
lg = L_frame + lext;
/*------ initialize window of TCX target : two halves of a squared
root of a hanning window the first part is as long as the overlap
length of past frame (ovlp_size) the second part is as long as
lext -----*/
/*----------- DECODE TCX PARAMETERS AND SYNTHESIZE LOWER-BAND SIGNAL (synth[]) ----------*/
/* if we lost all packets (i.e. 1 packet of TCX-20 ms, 2 packets of
the TCX-40 ms or 4 packets of the TCX-80ms), we lost the whole
coded frame extrapolation strategy: repeat lost excitation and
use extrapolated ISFs */
if ((n_pack == 1) &amt;&amt; (bad_frame[0] != 0)) {
/* repeat past excitation */
k = st->pitch_tcx;
for (i=0; i<L_frame; i++) {
exc[i] = 0.7f*exc[i-k];
}
mvr2r(synth-M, synth, M);
p_A = A;

#ifdef PW_UPDATE
mvr2r(st->mem_formant,mem_temp1,M);
mvr2r(st->mem_tilt,mem_temp2,TILT_ORDER);
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_UTIL_synthesis(p_A, &amt;exc[i_subfr], &amt;synth[i_subfr+M], L_SUBFR, &amt;synth[i_subfr], 0);
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma2, TILT_ORDER);
E_UTIL_residu(Ap1, &amt;synth[i_subfr+M], &amt;xnq[i_subfr], L_SUBFR);
E_UTIL_formant(&amt;xnq[i_subfr],Ap2,L_SUBFR,mem_temp1);
E_UTIL_tilt(&amt;xnq[i_subfr],Ap3,L_SUBFR,mem_temp2);
p_A += (M+1);
}
#endif
#ifndef PW_UPDATE
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_UTIL_synthesis(p_A, &amt;exc[i_subfr], &amt;synth[i_subfr+M], L_SUBFR, &amt;synth[i_subfr], 0);
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_residu(Ap, &amt;synth[i_subfr+M], &amt;xnq[i_subfr], L_SUBFR);
p_A += (M+1);
}
tmp = st->mem_wsyn;
E_UTIL_deemph(xnq, TILT_FAC, L_frame, &amt;tmp);
#endif

tmp = 0.7f*st->wsyn_rms;
st->wsyn_rms = tmp;
for (i=0; i<L_frame; i++) {
if (xnq[i] > tmp) {
xnq[i] = tmp;
} else {
if (xnq[i] < -tmp) {
xnq[i] = -tmp;
}
}
}

#ifdef PW_UPDATE
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma2, TILT_ORDER);
E_UTIL_detilt(&amt;xnq[i_subfr],Ap3,L_SUBFR,st->mem_tilt);
E_UTIL_deformant(&amt;xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant);
E_UTIL_synthesis(Ap1, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
p_A += (M+1);
}
#endif
#ifndef PW_UPDATE
E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &amt;(st->mem_wsyn));
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
p_A += (M+1);
}
#endif

/* zero windowed overlap (wovlp) for next frame */
for (i=0; i<lext; i++) {
st->wovlp[i]=0;
}
}
else
{
/*----- synthesize windowed TCX target (inverse FFT of decoded
spectrum + noise fill-in) using available info ------*/
/* decode noise level (fac_ns) (stored in 2nd packet on TCX80) */
index = *prm++;
if (n_pack == 4) {
bfi = bad_frame[1];
} else {
bfi = bad_frame[0];
}
if (bfi != 0) {
index = 0;
}
fac_ns = 0.1f*(8.0f - ((float)index));
/* read index of global TCX gain : erased bits are set to 1 to
minimize global gain if bad_frame set erased bits to default
value (0 or 1 depending on parameter) */
index = *prm++;
#ifdef NEW_TVC
/* decode gain between two bands */
index2 = *prm++;
gband = (float)index2 / (float)64.0;
/* decode parameters of multi-rate lattice VQ */
AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame);
/* amplify low half band with gain gband */
for (i = 0; i < lg/2; i++){
xri[i+lg/2] /= gband;
}
#else
/* decode parameters of multi-rate lattice VQ */
AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame);
#endif
if(any_loss) {
adapt_low_freq_deemph_ecu(xri,lg,st);
reconst_spect(xri,st->old_xri,n_pack,bad_frame,lg,st->last_mode,xnq);
/* generate random excitation buffer */
set_zero(xnq, lg);
rnd_ph16(&amt;(st->seed_tcx), &amt;xnq[lg/6], lg-(lg/6));
/*----------------------------------------------*
* noise fill-in on unquantized subvector *
* injected only from 1066Hz to 6400Hz. *
*----------------------------------------------*/
for(k=lg/6; k<lg; k+=8) {
tmp = 0.0;
for(i=k; i<k+8; i++) {
tmp += xri[i]*xri[i];
}
if (tmp == 0.0) {
for(i=k; i<k+8; i++) {
xri[i] = fac_ns*xnq[i];
}
}
}
} else {
/* generate random excitation buffer */
set_zero(xnq, lg);
rnd_ph16(&amt;(st->seed_tcx), &amt;xnq[lg/6], lg-(lg/6));

/*----------------------------------------------*
* noise fill-in on unquantized subvector *
* injected only from 1066Hz to 6400Hz. *
*----------------------------------------------*/
for(k=lg/6; k<lg; k+=8) {
tmp = 0.0;
for(i=k; i<k+8; i++) {
tmp += xri[i]*xri[i];
}
if (tmp == 0.0) {
for(i=k; i<k+8; i++) {
xri[i] = fac_ns*xnq[i];
}
}
}
#ifdef NEW_TVC
adap_pulse_deemph(xri, lg);
#else
adap_low_freq_deemph(xri, lg);
#endif
}
/* save tcx vector for next frame */
mvr2r(xri,st->old_xri,lg);
/* find pitch for bfi case */
st->pitch_tcx = find_mpitch(xri, lg);
/*-----------------------------------------------------------*
* 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. *
*-----------------------------------------------------------*/
xri[1] = 0.0; /* freq bin at 6400 Hz zeroed */
ifft9(xri, xnq, (short)lg);
/*-----------------------------------------------------------*
* decode TCX global gain, multiply xnq[] by gain. *
* windowing of xnq[] for TCX overlap. *
*-----------------------------------------------------------*/
bfi = 0; /* We never have a missing gain!!! */
gain = d_gain_tcx(index, xnq, lg, bfi, &amt;(st->wsyn_rms));
#ifdef GAIN_CONCEAL_OLA
gain_conceal_ola(&amt;gain,xnq,st->wovlp,st->ovlp_size);
#endif
for (i=0; i<lg; i++) {
xnq[i] *= gain;
}
#ifdef NEW_TVC
/*------ initialize window of TCX target : two halves of a squared
root of a hanning window the first part is as long as the overlap
length of past frame (ovlp_size) the second part is as long as
lext -----*/
if(st->ovlp_size==0){
lext=lext/2;
}

cos_window(window, st->ovlp_size, lext);
/* adaptive windowing on overlap (beginning and end of frame) */

for (i=0; i<st->ovlp_size; i++) {
xnq[i] *= window[i];
}
if (st->ovlp_size ==0){
for (i=0; i<lext; i++) {
xnq[i+L_frame+lext] *= window[st->ovlp_size+i];
}
}
else{
for (i=0; i<lext; i++) {
xnq[i+L_frame] *= window[st->ovlp_size+i];
}
}

//下面求解帧头的交迭信号合成语音
if(st->ovlp_size==0){
if (lext==16) {
mvr2r(&amt; st->wovlp[48], oldsynth, M);
tmp1= st->wovlp[80];
}
else if (lext==32) {
mvr2r(&amt; st->wovlp[32], oldsynth, M);
tmp1= st->wovlp[81];
}
else {
mvr2r( st->wovlp, oldsynth, M);
tmp1= st->wovlp[82];
}
#ifdef PW_UPDATE
mvr2r(&amt;st->wovlp[83], Ap1, M+1);
mvr2r(st->wovlp_ap2, Ap2, M+1);
mvr2r(st->wovlp_ap3, Ap3, TILT_ORDER+1);
set_zero(st->wovlp, L_OVLP);
set_zero(st->wovlp_ap2, 17);
set_zero(st->wovlp_ap3, 3);
#else
mvr2r(&amt;st->wovlp[83], Ap, M+1);
set_zero(st->wovlp, L_OVLP);
#endif
tmp2=L_frame+lext;
}

/*-----------------------------------------------------------*
* TCX overlap and add. Update memory for next overlap. *
*-----------------------------------------------------------*/
for (i=0; i<L_OVLP; i++) {
xnq[i] += st->wovlp[i];
}
/* save overlap for next frame */
if(st->ovlp_size==0){
for (i=0; i<lext; i++) {
st->wovlp[i] = xnq[i+L_frame+lext];
}
}
else{
for (i=0; i<lext; i++) {
st->wovlp[i] = xnq[i+L_frame];
}
}
for (i=lext; i<L_OVLP; i++) {
st->wovlp[i] = 0.0;
}

/*-----------------------------------------------------------*
* find excitation and synthesis *
*-----------------------------------------------------------*/
#ifdef PW_UPDATE
if(st->g_flg==0 &amt;&amt; st->ovlp_size==0){
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma3,TILT_ORDER);
E_UTIL_detilt(&amt;xnq[i_subfr+lext],Ap3,L_SUBFR,st->mem_tilt);
E_UTIL_deformant(&amt;xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant);
E_UTIL_synthesis(Ap1, &amt;xnq[i_subfr+lext], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
}
else{
if(st->ovlp_size==0){
E_UTIL_detilt(xnq,Ap3,lext,st->mem_tilt);
E_UTIL_deformant(xnq,Ap2,lext,st->mem_formant);
E_UTIL_synthesis(Ap1, xnq, st->gw_synth, lext, oldsynth, 0);
mvr2r(&amt;st->gw_synth[lext-M], ol_synth, M);

p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma3,TILT_ORDER);
E_UTIL_detilt(&amt;xnq[i_subfr+lext],Ap3,L_SUBFR,st->mem_tilt);
E_UTIL_deformant(&amt;xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant);
E_UTIL_synthesis(Ap1, &amt;xnq[i_subfr+lext], &amt;ol_synth[i_subfr+M], L_SUBFR, &amt;ol_synth[i_subfr], 0);
E_UTIL_residu(p_A, &amt;ol_synth[i_subfr+M], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
mvr2r(&amt;ol_synth[M], synth, L_frame);
st->mem_wsyn=tmp1;
}else{
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma3,TILT_ORDER);
E_UTIL_detilt(&amt;xnq[i_subfr],Ap3,L_SUBFR,st->mem_tilt);
E_UTIL_deformant(&amt;xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant);
E_UTIL_synthesis(Ap1, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
}
}
st->ovlp_size = lext;
#endif
#ifndef PW_UPDATE
if(st->g_flg==0 &amt;&amt; st->ovlp_size==0){
E_UTIL_f_preemph(&amt;xnq[lext], TILT_FAC, L_frame, &amt;(st->mem_wsyn));
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, &amt;xnq[i_subfr+lext], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}

}
else{
if(st->ovlp_size==0){
E_UTIL_f_preemph(xnq, TILT_FAC, tmp2, &amt;tmp1);
E_UTIL_synthesis(Ap, xnq, st->gw_synth, lext, oldsynth, 0);
mvr2r(&amt;st->gw_synth[lext-M], ol_synth, M);

p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, &amt;xnq[i_subfr+lext], &amt;ol_synth[i_subfr+M], L_SUBFR, &amt;ol_synth[i_subfr], 0);
E_UTIL_residu(p_A, &amt;ol_synth[i_subfr+M], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
mvr2r(&amt;ol_synth[M], synth, L_frame);
st->mem_wsyn=tmp1;
}else{
E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &amt;(st->mem_wsyn));
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
}
}
st->ovlp_size = lext;
#endif
}
return;
#else
/*------ initialize window of TCX target : two halves of a squared
root of a hanning window the first part is as long as the overlap
length of past frame (ovlp_size) the second part is as long as
lext -----*/
cos_window(window, st->ovlp_size, lext);
/* adaptive windowing on overlap (beginning and end of frame) */
for (i=0; i<st->ovlp_size; i++) {
xnq[i] *= window[i];
}
for (i=0; i<lext; i++) {
xnq[i+L_frame] *= window[st->ovlp_size+i];
}
/*-----------------------------------------------------------*
* TCX overlap and add. Update memory for next overlap. *
*-----------------------------------------------------------*/
for (i=0; i<L_OVLP; i++) {
xnq[i] += st->wovlp[i];
}
/* save overlap for next frame */
for (i=0; i<lext; i++) {
st->wovlp[i] = xnq[i+L_frame];
}
for (i=lext; i<L_OVLP; i++) {
st->wovlp[i] = 0.0;
}
st->ovlp_size = lext;
/*-----------------------------------------------------------*
* find excitation and synthesis *
*-----------------------------------------------------------*/
#ifdef PW_UPDATE
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
paraChoose(p_A,&amt;gamma1,&amt;gamma2,&amt;gamma3);
E_LPC_a_weight(p_A, Ap1, gamma1, M);
E_LPC_a_weight(p_A, Ap2, gamma2, M);
E_LPC_a_weight(p_A, Ap3, gamma3,TILT_ORDER);
E_UTIL_detilt(&amt;xnq[i_subfr],Ap3,L_SUBFR,st->mem_tilt);
E_UTIL_deformant(&amt;xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant);
E_UTIL_synthesis(Ap1, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
#endif
#ifndef PW_UPDATE
E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &amt;(st->mem_wsyn));
p_A = A;
for (i_subfr=0; i_subfr<L_frame; i_subfr+=L_SUBFR) {
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, &amt;xnq[i_subfr], &amt;synth[i_subfr], L_SUBFR, &amt;synth[i_subfr-M], 0);
E_UTIL_residu(p_A, &amt;synth[i_subfr], &amt;exc[i_subfr], L_SUBFR);
p_A += (M+1);
}
#endif
}
return;
#endif
}
static int find_mpitch(float xri[], int lg)
{
float tmp, max, pitch, mpitch;
int i, n;
max = 0.0;
n = 2;
/* find maximum below 400Hz */
for (i=2; i<lg/16; i+=2) {
tmp = xri[i]*xri[i] + xri[i+1]*xri[i+1];
if (tmp > max) {
max = tmp;
n = i;
}
}
pitch = (float)lg*(2.0f/(float)n);
/* find pitch multiple under 20ms */
if (pitch >= 256.0f) {
n = 256;
} else {
mpitch = pitch;
while (mpitch < 256.0f) {
mpitch += pitch;
}
n = (int)floor(mpitch-pitch);
}
return(n);
}