www.pudn.com > AVS_M_ver10.rar > cod_new_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"
#include "../include/s_util.h"
/* NEW_STEREO */
/* TO BOTTOM OF THIS FILE */
#define EPS 0.001f
// initial stereo struction and parameter
void init_new_stereo_encoder(NEW_STEREO_DATA *newStereo, //(i/o): Encoder states
float bitrate) //(i): encoding bitrate
{
int i;
set_zero(newStereo->old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
set_zero(newStereo->old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
set_zero(newStereo->mem_side_error, 4);
set_zero(newStereo->mem_mono_error, 4);
set_zero(newStereo->old_AqLF, 5*(M+1));
for (i = 0;i < 5;i++)
{
newStereo->old_AqLF[i*(M+1)]=1.0f;
}
set_zero(newStereo->pre_left_gain, MF_GAIN_NUM);
set_zero(newStereo->pre_right_gain, MF_GAIN_NUM);
newStereo->mem_ovlp_size_enc = 0;
newStereo->signalType.is_transient = 0;
newStereo->signalType.min_energy = 10.0f;
newStereo->signalType.attack_threshold = 8.0f;
newStereo->signalType.prev_frame_energy = 0.0f;
newStereo->bitrate = bitrate;
if (bitrate <= 32.0f)
{
newStereo->lowfreq_end_num_l = 128;
newStereo->lowfreq_end_num_s = newStereo->lowfreq_end_num_l / 4;
}
else
{
newStereo->lowfreq_end_num_l = 192;
newStereo->lowfreq_end_num_s = newStereo->lowfreq_end_num_l / 4;
}
// side exc estimation
set_zero(newStereo->wiener_filter, HI_FILT_ORDER*4);
set_zero(newStereo->old_mono_exc, HI_FILT_ORDER);
newStereo->filt_energy_threshold = 0.0f;
set_zero(newStereo->old_wh_q, HI_FILT_ORDER);
}
static void MakeSignalTypeAnalysis(NEW_STEREO_DATA *newStereo, SIGNAL_TYPE* signalType, const float *side_exc)
{
int i, b;
float block_energy[BLOCK_NUM+1];
int block_len = L_FRAME_PLUS/BLOCK_NUM;
float attack_threshold = signalType->attack_threshold;
float min_attack = signalType->min_energy;
block_energy[0] = signalType->prev_frame_energy;
for (b = 0; b < BLOCK_NUM; b++)
{
block_energy[b+1] = 0.0f;
for (i = b*block_len; i < (b+1)*block_len; i++)
{
block_energy[b+1] += side_exc[i] * side_exc[i];
}
}
signalType->prev_frame_energy = block_energy[BLOCK_NUM];
signalType->is_transient = 0;
for (b = 1; b < BLOCK_NUM+1; b++)
{
if ((block_energy[b] > attack_threshold * block_energy[b-1]) &amt;&amt; (block_energy[b] > min_attack))
{
signalType->is_transient = 1;
break;
}
}
}
static void MakeFFTTransform(NEW_STEREO_DATA *newStereo,
SIGNAL_TYPE* signalType,
const float *est_side_ch,
const float *side_ch,
const float *mono_ch,
float *side_fft,
float *mono_fft,
float *left_fft,
float *right_fft,
float *est_left_fft,
float *est_right_fft)
{
int i, w;
int L_frame, lext, lg;
float window[256];
int ovlp_size;
// memory can be saved by reusing some place
float est_xn_side[L_FRAME_PLUS+L_OVLP];
float xn_side[L_FRAME_PLUS+L_OVLP];
float xn_mono[L_FRAME_PLUS+L_OVLP];
float est_side_fft[L_FRAME_PLUS+L_OVLP];
if (!signalType->is_transient) // smooth
{
mvr2r(est_side_ch, est_xn_side, L_FRAME_PLUS+L_OVLP);
mvr2r(side_ch, xn_side, L_FRAME_PLUS+L_OVLP);
mvr2r(mono_ch, xn_mono, L_FRAME_PLUS+L_OVLP);
lext = L_OVLP;
L_frame =L_FRAME_PLUS;
ovlp_size = newStereo->mem_ovlp_size_enc;
lg = L_frame + lext;
// built window for overlaps section
cos_window(window, ovlp_size, lext);
// est_xn_side[] etc windowing for DFT overlap
for (i = 0; i < ovlp_size; i++)
{
est_xn_side[i] *= window[i];
xn_side[i] *= window[i];
xn_mono[i] *= window[i];
}
for (i = 0; i < lext; i++)
{
est_xn_side[L_frame+i] *= window[ovlp_size+i];
xn_side[L_frame+i] *= window[ovlp_size+i];
xn_mono[L_frame+i] *= window[ovlp_size+i];
}
/*-----------------------------------------------------------*
* Compute the FFT of xn[]. *
* 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. *
*-----------------------------------------------------------*/
fft9(est_xn_side, est_side_fft, (short)lg);
est_side_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
fft9(xn_side, side_fft, (short)lg);
side_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
fft9(xn_mono, mono_fft, (short)lg);
mono_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
newStereo->mem_ovlp_size_enc = L_OVLP;
}
else
{
lext = L_OVLP/4;
L_frame =L_FRAME_PLUS/4;
lg = L_frame + lext;
for (w = 0; w < 4; w++)
{
float *cur_est_side_fft = est_side_fft + w * lg;
float *cur_side_fft = side_fft + w * lg;
float *cur_mono_fft = mono_fft + w * lg;
mvr2r(est_side_ch + w * lg, est_xn_side, lg); // it IS lg NOT L_frame, because wiener_estimation ovlp
mvr2r(side_ch + w * L_frame, xn_side, lg);
mvr2r(mono_ch + w * L_frame, xn_mono, lg);
ovlp_size = newStereo->mem_ovlp_size_enc;
cos_window(window, ovlp_size, lext);
// est_xn_side[] windowing for DFT overlap
for (i = 0; i < ovlp_size; i++)
{
est_xn_side[i] *= window[i];
xn_side[i] *= window[i];
xn_mono[i] *= window[i];
}
for (i = 0; i < lext; i++)
{
est_xn_side[L_frame+i] *= window[ovlp_size+i];
xn_side[L_frame+i] *= window[ovlp_size+i];
xn_mono[L_frame+i] *= window[ovlp_size+i];
}
fft9(est_xn_side, cur_est_side_fft, (short)lg);
cur_est_side_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
fft9(xn_side, cur_side_fft, (short)lg);
cur_side_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
fft9(xn_mono, cur_mono_fft, (short)lg);
cur_mono_fft[1] = 0.0f; // freq bin at 6400 Hz zeroed
newStereo->mem_ovlp_size_enc = L_OVLP/4;
}
}
// get left &amt; right signal
for (i = 0; i < L_FRAME_PLUS+L_OVLP; i++)
{
left_fft[i] = mono_fft[i] + side_fft[i];
right_fft[i] = mono_fft[i] - side_fft[i];
est_left_fft[i] = mono_fft[i] + est_side_fft[i];
est_right_fft[i] = mono_fft[i] - est_side_fft[i];
}
}
// find gain (for low freq AVQ)
static float get_gain_freq(const float x[],
const float y[],
int n)
{
float ener_x = 0.0f, ener_y = 1e-6f;
float gain;
float x_mag, y_mag;
short i;
for (i = 0; i < n/2; i++)
{
x_mag = x[2*i]*x[2*i] + x[2*i+1]*x[2*i+1];
y_mag = y[2*i]*y[2*i] + y[2*i+1]*y[2*i+1];
ener_x += (float)sqrt(x_mag*y_mag);
ener_y += (float)sqrt(y_mag*y_mag);
}
gain = ener_x / ener_y;
return gain;
}
// quantize gain (for low freq AVQ)
static int q_gain_new_tcx( // output: return quantization index
float code[], // (i) : quantized vector
int lcode, // (i) : frame size
float *gain // in/out: quantized gain
)
{
int i, index;
float tmp, gcode0, gcode;
/* energy */
tmp = 0.01f;
for(i=0; i<lcode; i++) {
tmp += code[i] * code[i];
}
gcode0 = (float)sqrt(tmp/((float)lcode));
/* quantize gain of code */
gcode = *gain * gcode0;
if (gcode < FLT_MIN) {
gcode = FLT_MIN;
}
tmp = 25.0f * (float)log10(gcode);
index = (int)floor(tmp + 0.5);
if (index < 0) {
index = 0;
}
if (index > 127) {
index = 127;
}
gcode = (float)pow(10.0, ((float)index)/25.0) / gcode0;
*gain = gcode;
return(index);
}
static void MakeLowFreqCoding(NEW_STEREO_DATA *newStereo,
const float *side_fft,
int low_freq_num,
int used_bits, // (i)number of AVQ bits
int *prm) // (o)AVQ bits stream
{
int i;
float fac_ns;
float syn_side_fft[NEW_STEREO_LF_MAX_NUM_L];
float syn_side_fft_q[NEW_STEREO_LF_MAX_NUM_L];
float gain;
float gh, gg; // wlei [20070604]
mvr2r(side_fft, syn_side_fft, low_freq_num);
/*-----------------------------------------------------------*
* Spectral algebraic quantization *
* with adaptive low frequency emphasis/deemphasis. *
* Noise factor is the average level of unquantized freq. *
*-----------------------------------------------------------*/
#ifdef NEW_TVC
adap_pulse_emph(syn_side_fft, 4*low_freq_num);
used_bits -= (7); /* gain = 7 bits */
AVQ_gain_allocator(syn_side_fft, low_freq_num, used_bits, &amt;gh, &amt;gg); // wlei [20070604]
fac_ns = AVQ_cod(syn_side_fft, prm+1, used_bits, low_freq_num/8, &amt;gh, &amt;gg);
#else
adap_low_freq_emph(syn_side_fft, 4*low_freq_num);
used_bits -= (7); /* gain = 7 bits */
fac_ns = AVQ_cod(syn_side_fft, prm+1, used_bits, low_freq_num/8);
#endif
for(i=0; i<low_freq_num; i++)
{
syn_side_fft_q[i] = (float)prm[i+1];
}
/*-----------------------------------------------------------*
* 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(syn_side_fft_q, 4*low_freq_num);
#else
adap_low_freq_deemph(syn_side_fft_q, 4*low_freq_num);
#endif
// find and quantize gain
gain = get_gain_freq(syn_side_fft, syn_side_fft_q, low_freq_num);
prm[0] = q_gain_new_tcx(syn_side_fft_q, low_freq_num, &amt;gain);
}
// mid-freq gain's two-dimension VQ
static void VQ_gain(float *x, //(i/o) input vector/(o)quantized vector
const float *dico, //(i) code book
int dim, // (i)dimension
int dico_size, // (i)code book size
int *index) // (o)VQ index
{
float dist_min;
float dist, temp;
const float *p_dico;
int i, j;
dist_min = 1.0e30f;
p_dico = dico;
for (i = 0; i < dico_size; i++)
{
dist = 0.0;
for (j = 0; j < dim; j++)
{
temp = x[j] - *p_dico++;
dist += temp * temp;
}
if (dist < dist_min)
{
dist_min = dist;
*index = i;
}
}
for (j = 0; j < dim; j++)
{
x[j] = dico[*index*dim+j];
}
return;
}
static void MakeMidFreqCoding(NEW_STEREO_DATA *newStereo,
int is_transient, // (i)signal type:0 or 1
const float *left_fft,
const float *right_fft,
const float *est_left_fft,
const float *est_right_fft,
int mid_freq_num,
float *left_gain,
float *right_gain,
float *quant_left_gain,
float *quant_right_gain,
int w, // (i)coding window number
int gain_num,
int *param, // (o)bits stream
float gain_correlation) // cross-correlation between left and right channel
{
int b, i;
float left_psd[(L_FRAME_PLUS+L_OVLP)/2];
float right_psd[(L_FRAME_PLUS+L_OVLP)/2];
float est_left_psd[(L_FRAME_PLUS+L_OVLP)/2];
float est_right_psd[(L_FRAME_PLUS+L_OVLP)/2];
int mid_psd_len = mid_freq_num / 2;
int gain_len = mid_psd_len / gain_num;
float left_energy;
float right_energy;
float est_left_energy;
float est_right_energy;
float tmpGain[HI_GAIN_ORDER];
float left_error[MF_GAIN_NUM];
float right_error[MF_GAIN_NUM];
for (i = 0; i < mid_psd_len; i++)
{
left_psd[i] = left_fft[2*i]*left_fft[2*i] + left_fft[2*i+1]*left_fft[2*i+1];
right_psd[i] = right_fft[2*i]*right_fft[2*i] + right_fft[2*i+1]*right_fft[2*i+1];
est_left_psd[i] = est_left_fft[2*i]*est_left_fft[2*i] + est_left_fft[2*i+1]*est_left_fft[2*i+1];
est_right_psd[i] = est_right_fft[2*i]*est_right_fft[2*i] + est_right_fft[2*i+1]*est_right_fft[2*i+1];
}
for (b = 0; b < gain_num; b++)
{
left_energy = 0.001f;
right_energy = 0.001f;
est_left_energy = 0.001f;
est_right_energy = 0.001f;
for (i = b * gain_len; i < (b+1) * gain_len; i++)
{
left_energy += left_psd[i];
right_energy += right_psd[i];
est_left_energy += est_left_psd[i];
est_right_energy += est_right_psd[i];
}
left_gain[b] = left_energy/est_left_energy;
right_gain[b] = right_energy/est_right_energy;
left_gain[b] = 10.0f * log10(left_gain[b] + EPS);
right_gain[b] = 10.0f * log10(right_gain[b] + EPS);
// attenuate gains in case of anti-correlation
if (gain_correlation < 0)
{
if (left_gain[b] > 0)
{
left_gain[b] = max(0.0f, left_gain[b]+gain_correlation);
}
if (right_gain[b] > 0)
{
right_gain[b] = max(0.0f, right_gain[b]+gain_correlation);
}
}
}
if (newStereo->signalType.is_transient == 0)
{
for (b = 0; b < gain_num; b++)
{
left_error[b] = (left_gain[b]-cb_gain_hi_mean_smooth[0]) - 0.5f*newStereo->pre_left_gain[b];
right_error[b] = (right_gain[b]-cb_gain_hi_mean_smooth[1]) - 0.5f*newStereo->pre_right_gain[b];
tmpGain[0] = left_error[b];
tmpGain[1] = right_error[b];
VQ_gain(tmpGain, dico_gain_side_hf_smooth, HI_GAIN_ORDER, SIZE_GAIN_HI_MSVQ_5A, param+b);
quant_left_gain[b] = tmpGain[0] + cb_gain_hi_mean_smooth[0] + 0.5f*newStereo->pre_left_gain[b];
quant_right_gain[b] = tmpGain[1] + cb_gain_hi_mean_smooth[1] + 0.5f*newStereo->pre_right_gain[b];
quant_left_gain[b] = (float)pow(10.0, 0.05*quant_left_gain[b]);
quant_right_gain[b] = (float)pow(10.0, 0.05*quant_right_gain[b]);
newStereo->pre_left_gain[b] = tmpGain[0] + 0.5f*newStereo->pre_left_gain[b];
newStereo->pre_right_gain[b] = tmpGain[1] + 0.5f*newStereo->pre_right_gain[b];
}
}
else
{
for (b = 0; b < gain_num; b++)
{
left_error[b] = left_gain[b] - cb_gain_hi_mean_quick[0];
right_error[b] = right_gain[b] - cb_gain_hi_mean_quick[1];
tmpGain[0] = left_error[b];
tmpGain[1] = right_error[b];
VQ_gain(tmpGain, dico_gain_side_hf_quick, HI_GAIN_ORDER, SIZE_GAIN_HI_MSVQ_5A, param+b);
tmpGain[0] += cb_gain_hi_mean_quick[0];
tmpGain[1] += cb_gain_hi_mean_quick[1];
quant_left_gain[b] = (float)pow(10.0, 0.05*tmpGain[0]);
quant_right_gain[b] = (float)pow(10.0, 0.05*tmpGain[1]);
}
}
}
static void MakeStereoCoding(NEW_STEREO_DATA *newStereo,
SIGNAL_TYPE* signalType,
const float *side_fft,
const float *left_fft,
const float *right_fft,
const float *est_left_fft,
const float *est_right_fft,
int nbits,
int *param)
{
int low_freq_num;
int mid_freq_num;
int w, lg;
int *prm;
float *p_left_gain;
float *p_right_gain;
float *p_quant_left_gain;
float *p_quant_right_gain;
int gain_num;
int lf_bits;
int wiener_bits;
float gain_corr;
int hf_bits = 40; // number of mid-freq gains bits
prm = param + 8; // 8 mid-freq's gain
if (signalType->is_transient == 0) // smooth frame
{
low_freq_num = newStereo->lowfreq_end_num_l;
mid_freq_num = L_FRAME_PLUS + L_OVLP - low_freq_num;
p_left_gain = newStereo->left_gain;
p_right_gain = newStereo->right_gain;
p_quant_left_gain = newStereo->quant_left_gain;
p_quant_right_gain = newStereo->quant_right_gain;
gain_num = MF_GAIN_NUM;
gain_corr = newStereo->gain_correlation[0];
wiener_bits = 7;
lf_bits = nbits - wiener_bits - hf_bits; // mid-freq gain
MakeLowFreqCoding(newStereo,
side_fft,
low_freq_num,
lf_bits,
prm);
MakeMidFreqCoding(newStereo,
signalType->is_transient,
left_fft+low_freq_num,
right_fft+low_freq_num,
est_left_fft+low_freq_num,
est_right_fft+low_freq_num,
mid_freq_num,
p_left_gain,
p_right_gain,
p_quant_left_gain,
p_quant_right_gain,
0,
gain_num,
param,
gain_corr);
}
else
{
lg = (L_FRAME_PLUS+L_OVLP)/4;
low_freq_num = newStereo->lowfreq_end_num_s;
mid_freq_num = lg - low_freq_num;
gain_num = MF_GAIN_NUM/4;
if (newStereo->bitrate < 32.0f)
{
wiener_bits = 4*4;
}
else
{
wiener_bits = 7*4;
}
lf_bits = nbits - hf_bits - wiener_bits - 3; // 3:unused bits
for (w = 0; w < 4; w++)
{
float *cur_side_fft = side_fft + w * lg;
float *cur_left_fft = left_fft + w * lg;
float *cur_right_fft = right_fft + w * lg;
float *cur_est_left_fft = est_left_fft + w * lg;
float *cur_est_right_fft = est_right_fft + w * lg;
int *cur_prm = prm + w * (1+low_freq_num+low_freq_num/8); //1 global gain
p_left_gain = newStereo->left_gain + w * gain_num;
p_right_gain = newStereo->right_gain + w * gain_num;
p_quant_left_gain = newStereo->quant_left_gain + w * gain_num;
p_quant_right_gain = newStereo->quant_right_gain + w * gain_num;
gain_corr = newStereo->gain_correlation[w];
MakeLowFreqCoding(newStereo,
cur_side_fft,
low_freq_num,
lf_bits/4,
cur_prm);
MakeMidFreqCoding(newStereo,
signalType->is_transient,
cur_left_fft+low_freq_num,
cur_right_fft+low_freq_num,
cur_est_left_fft+low_freq_num,
cur_est_right_fft+low_freq_num,
mid_freq_num,
p_left_gain,
p_right_gain,
p_quant_left_gain,
p_quant_right_gain,
w,
gain_num,
param+w*gain_num,
gain_corr);
}
}
}
/* filter smoother */
static void smooth_ener_filter(float *filter,
float *threshold)
{
float tmp, ener,old_ener;
int i;
/* compute energy over subframe */
ener = 0.0001f;
for (i=0; i<HI_FILT_ORDER; i++)
{
ener += filter[i]*filter[i];
}
/* in any case limit the filter energy */
old_ener = ener;
if (ener > 16.0f){
ener= 16.0f;
}
/* if energy<threshold, add 1.5 dB and saturate to threshold
else substract 1.5 dB and saturate to threshold */
tmp = ener;
if (tmp < *threshold)
{
tmp = tmp*1.414f;
if (tmp > *threshold)
{
tmp = *threshold;
}
}
else {
tmp = tmp/1.414f;
if (tmp < *threshold)
{
tmp = *threshold;
}
}
/* set the threshold for next subframer to the current modified energy */
*threshold = tmp;
/* apply correction scale factor to HF signal */
tmp = (float)sqrt(tmp/old_ener);
for (i=0; i<HI_FILT_ORDER; i++)
{
filter[i] *= tmp;
}
return;
}
/* filter quantizer */
static void quant_filt(float h[], /* i/o */
float old_h[], /* i/o */
int **prm,
const PMSVQ *filt_hi_pmsvq
)
{
pmsvq(h, prm, h, old_h, filt_hi_pmsvq);
}
// high-pass filter
static void hp1K_12k8(const float *orig_signal,
float *filted_signal,
float *mem,
int lg)
{
int i;
float x0, x1, x2;
float y0, y1, y2;
y1 = mem[0];
y2 = mem[1];
x0 = mem[2];
x1 = mem[3];
for (i = 0; i < lg; i++)
{
x2 = x1;
x1 = x0;
x0 = orig_signal[i];
y0 = y1 * 1.85229f + y2 * -0.86314f + x0 * 0.9278487343389f + x1 * -1.8556974686778f + x2 * 0.9278487343389f;
filted_signal[i] = y0;
y2 = y1;
y1 = y0;
}
mem[0] = ((y1 > 1e-10) | (y1 < -1e-10)) ? y1 : 0;
mem[1] = ((y2 > 1e-10) | (y2 < -1e-10)) ? y2 : 0;
mem[2] = ((x0 > 1e-10) | (x0 < -1e-10)) ? x0 : 0;
mem[3] = ((x1 > 1e-10) | (x1 < -1e-10)) ? x1 : 0;
}
static void GetEstimatedSideExc(NEW_STEREO_DATA *newStereo,
int nIsTransient,
const float *side_exc,
const float *mono_exc,
float *est_side_exc,
int est_len,
int *param)
{
int k, t, j, i;
float tmp_mono_exc[L_FRAME_PLUS+L_OVLP+HI_FILT_ORDER];
float filted_side_exc[L_FRAME_PLUS+L_OVLP];
float filted_mono_exc[L_FRAME_PLUS+L_OVLP];
/* covariance matrix */
float r[HI_FILT_ORDER][HI_FILT_ORDER];
float c[HI_FILT_ORDER];
float *p_h = newStereo->wiener_filter;
float *x, *y;
int *prm;
float energy_right;
float energy_left;
float energy_mono;
#if 1
hp1K_12k8(side_exc, filted_side_exc, newStereo->mem_side_error, est_len);
hp1K_12k8(mono_exc, filted_mono_exc, newStereo->mem_mono_error, est_len);
#else
mvr2r(side_exc, filted_side_exc, est_len);
mvr2r(mono_exc, filted_mono_exc, est_len);
#endif
mvr2r(newStereo->old_mono_exc, tmp_mono_exc, HI_FILT_ORDER);
mvr2r(filted_mono_exc, tmp_mono_exc+HI_FILT_ORDER, est_len);
mvr2r(filted_mono_exc+L_FRAME_PLUS-HI_FILT_ORDER, newStereo->old_mono_exc, HI_FILT_ORDER);
if (nIsTransient == 0) // smooth
{
newStereo->filt_hi_pmsvq = &amt;filt_hi_pmsvq7;
prm = param;
/* set signal pointers */
x = tmp_mono_exc+HI_FILT_ORDER;
// y = side_exc;
y = filted_side_exc;
/* compute cross-correlation terms */
for (k = 0; k < HI_FILT_ORDER; k++)
{
c[k] = 0.0f;
for (t = 0; t < est_len; t++)
{
c[k] += y[t]*x[t-k];
}
}
/* compute correlation matrix */
for (k = 0; k < HI_FILT_ORDER; k++)
{
for (j = k; j < HI_FILT_ORDER; j++)
{
r[k][j] = 0.0f;
for (t = 0; t < est_len; t++)
{
r[k][j] += x[t-k]*x[t-j];
}
}
}
/* compute a solution to the linear system */
if (cholsolc(r, c, p_h, HI_FILT_ORDER))
{
/* cholesky failed use panning */
for (k = 1; k < HI_FILT_ORDER; k++)
{
p_h[k] = 0.0f;
}
p_h[0] = c[0]/(r[0][0]+1.0f);
}
energy_left = 0.001f;
energy_right = 0.001f;
energy_mono = 0.001f;
for (t = 0; t < est_len; t++)
{
/* mono + side */
energy_left += (x[t]+y[t]) * (x[t]+y[t]);
/* mono */
energy_mono += x[t] * x[t];
/* mono - side */
energy_right += (x[t]-y[t]) * (x[t]-y[t]);
}
newStereo->gain_correlation[0] = (4.0f*energy_mono)/(energy_left+energy_right);
newStereo->gain_correlation[0] = 10.0f*(float)log10(newStereo->gain_correlation[0]);
/* wiener filter energy smoothing */
smooth_ener_filter(p_h, &amt;newStereo->filt_energy_threshold);
/* quantize the filters*/
quant_filt(p_h, newStereo->old_wh_q, &amt;prm, newStereo->filt_hi_pmsvq);
/* local synthesis */
fir_filt(p_h, HI_FILT_ORDER, x, est_side_exc, est_len);
}
else // quick signal
{
int est_len_quick = est_len / 4;
if (newStereo->bitrate < 32.0)
{
newStereo->filt_hi_pmsvq = &amt;filt_hi_pmsvq4;
}
else
{
newStereo->filt_hi_pmsvq = &amt;filt_hi_pmsvq7;
}
for (i = 0; i < 4; i++)
{
prm = param + i * 2; // maximum: 2 msvq stages (filt)
/* set signal pointers */
x = tmp_mono_exc + HI_FILT_ORDER + i*256;
// y = side_exc;
y = filted_side_exc + i*256;
/* compute cross-correlation terms */
for (k = 0; k < HI_FILT_ORDER; k++)
{
c[k] = 0.0f;
for (t = 0; t < est_len_quick; t++)
{
c[k] += y[t]*x[t-k];
}
}
/* compute correlation matrix */
for (k = 0; k < HI_FILT_ORDER; k++)
{
for (j = k; j < HI_FILT_ORDER; j++)
{
r[k][j] = 0.0f;
for (t = 0; t < est_len_quick; t++)
{
r[k][j] += x[t-k]*x[t-j];
}
}
}
/* compute a solution to the linear system */
if (cholsolc(r, c, p_h, HI_FILT_ORDER))
{
/* cholesky failed use panning */
for (k = 1; k < HI_FILT_ORDER; k++)
{
p_h[k] = 0.0f;
}
p_h[0] = c[0]/(r[0][0]+1.0f);
}
energy_left = 0.001f;
energy_right = 0.001f;
energy_mono = 0.001f;
for (t = 0; t < est_len_quick; t++)
{
/* mono + side */
energy_left += (x[t]+y[t]) * (x[t]+y[t]);
/* mono */
energy_mono += x[t] * x[t];
/* mono - side */
energy_right += (x[t]-y[t]) * (x[t]-y[t]);
}
newStereo->gain_correlation[i] = (4.0f*energy_mono)/(energy_left+energy_right);
newStereo->gain_correlation[i] = 10.0f*(float)log10(newStereo->gain_correlation[i]);
/* wiener filter energy smoothing */
smooth_ener_filter(p_h, &amt;newStereo->filt_energy_threshold);
/* quantize the filters*/
quant_filt(p_h, newStereo->old_wh_q, &amt;prm, newStereo->filt_hi_pmsvq);
// est_side_exc has 32-point overlap every other 288-point!!!!! because it is est_len_quick(288), NO 256
fir_filt(p_h, HI_FILT_ORDER, x, est_side_exc+i*est_len_quick, est_len_quick);
p_h += HI_FILT_ORDER;
}
}
}
void cod_new_stereo_side(const float *sig_left, // (i)mono channel
const float *sig_right, // (i)right channel
int brMode,
float AqLF[],
int param_stereo[], // (o)Encoded parameters
NEW_STEREO_DATA *newStereo) //(i/o): Encoder states
{
int i_subfr, k;
int nbits;
float mono_exc[L_FRAME_PLUS+NEW_STEREO_DELAY];//NEW_STEREO_DELAY >= L_OVLP
float side_exc[L_FRAME_PLUS+NEW_STEREO_DELAY];
float est_side_exc[L_FRAME_PLUS+L_OVLP];
float *p_Aq;
int *prm = NULL;
float old_speech_side[L_TOTAL_ST+NEW_STEREO_DELAY];
float *speech_side, *new_speech_side;
float old_speech_mono[L_TOTAL_ST+NEW_STEREO_DELAY];
float *speech_mono, *new_speech_mono;
set_zero(old_speech_side, L_TOTAL_ST+NEW_STEREO_DELAY);
set_zero(old_speech_mono, L_TOTAL_ST+NEW_STEREO_DELAY);
new_speech_side = old_speech_side + L_OLD_SPEECH_ST + NEW_STEREO_DELAY;
speech_side = old_speech_side + L_TOTAL_ST - L_FRAME_PLUS - L_A_MAX - L_BSP;
new_speech_mono = old_speech_mono + L_OLD_SPEECH_ST + NEW_STEREO_DELAY;
speech_mono = old_speech_mono + L_TOTAL_ST - L_FRAME_PLUS - L_A_MAX - L_BSP;
mvr2r(newStereo->old_speech_side, old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
mvr2r(newStereo->old_speech_mono, old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
mix_ch(sig_left, sig_right, new_speech_mono, L_FRAME_PLUS, 1.0f, 1.0f);
mvr2r(sig_right, new_speech_side, L_FRAME_PLUS);
mvr2r(old_speech_side+L_FRAME_PLUS, newStereo->old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
mvr2r(old_speech_mono+L_FRAME_PLUS, newStereo->old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY);
// calc available bits
/* number of bits per frame (80 ms) */
// 1 bit: signal type
nbits = StereoNbits[brMode];
nbits -= 1; // signal type,
// get old mono lf exc
p_Aq = newStereo->old_AqLF;
residu(p_Aq, M, &amt;speech_mono[0], &amt;mono_exc[0], L_SUBFR/2);
residu(p_Aq, M, &amt;speech_side[0], &amt;side_exc[0], L_SUBFR/2);
p_Aq += (M+1);
for (i_subfr = L_SUBFR/2; i_subfr < 4*L_SUBFR+L_SUBFR/2; i_subfr+=L_SUBFR)
{
residu(p_Aq, M, &amt;speech_mono[i_subfr], &amt;mono_exc[i_subfr], L_SUBFR);
residu(p_Aq, M, &amt;speech_side[i_subfr], &amt;side_exc[i_subfr], L_SUBFR);
p_Aq += (M+1);
}
// get mono lf exc, forced delay 288 in order to synchonize with decoder
p_Aq = AqLF;
for (i_subfr = L_SUBFR/2+4*L_SUBFR; i_subfr < L_FRAME_PLUS+L_SUBFR/2+4*L_SUBFR; i_subfr+=L_SUBFR)
{
residu(p_Aq, M, &amt;speech_mono[i_subfr], &amt;mono_exc[i_subfr], L_SUBFR);
residu(p_Aq, M, &amt;speech_side[i_subfr], &amt;side_exc[i_subfr], L_SUBFR);
p_Aq += (M+1);
}
mvr2r(&amt;AqLF[11*(M+1)], newStereo->old_AqLF, 5*(M+1));
// get real side
for (k = 0; k < L_FRAME_PLUS+L_OVLP; k++)
{
side_exc[k] = mono_exc[k] - side_exc[k];
}
MakeSignalTypeAnalysis(newStereo, &amt;newStereo->signalType, side_exc);
param_stereo[0] = newStereo->signalType.is_transient;
// wiener estimation
prm = param_stereo + 1;
GetEstimatedSideExc(newStereo,
newStereo->signalType.is_transient,
side_exc,
mono_exc,
est_side_exc,
L_FRAME_PLUS+L_OVLP,
prm);
// time-frequency transform
MakeFFTTransform(newStereo,
&amt;newStereo->signalType,
est_side_exc,
side_exc,
mono_exc,
newStereo->side_fft,
newStereo->mono_fft,
newStereo->left_fft,
newStereo->right_fft,
newStereo->est_left_fft,
newStereo->est_right_fft);
// low-frequency AVQ coding and mid-frequency gain control
prm = param_stereo + (1+8); // 1: signal type; 8: wiener VQ
MakeStereoCoding(newStereo,
&amt;newStereo->signalType,
newStereo->side_fft,
newStereo->left_fft,
newStereo->right_fft,
newStereo->est_left_fft,
newStereo->est_right_fft,
nbits,
prm);
}
static int unpack4bits_d(int nbits, int *prm, short *ptr)
{
int i;
i=0;
while (nbits > 4)
{
int2bin(prm[i], 4, ptr);
ptr += 4;
nbits -= 4;
i++;
}
int2bin(prm[i], nbits, ptr);
i++;
return(i);
}
void enc_prm_new_stereo(int param[], /* (i) : parameters */
short serial[], /* (o) : serial bits stream */
int nbits_pack, /* (i) : number of bits per packet of 20ms*/
int nbits_bwe, /* (i) : number of BWE bits per 20ms */
int brMode,
NEW_STEREO_DATA *newStereo
)
{
int nbits;
int k,j;
short *ptr = NULL;
int *prm = NULL;
int mod[NB_DIV],nbits_AVQ[NB_DIV];
int n_pack;
int prm_AVQ[(NBITS_MAX/4)+N_PACK_MAX];
int hf_bits = 0;
int si_bits = 0;
int signal_type;
int low_freq_len_l = newStereo->lowfreq_end_num_l;
int low_freq_len_s = newStereo->lowfreq_end_num_s;
/*----------------------------------------------------------*
* Set number of bits used for stereo (per packet of 20 ms) *
* When stereo is transmitted, the bit ordering is: *
* serial: mode (2bits), core, stereo, 2xBWE(2x16bits) *
*----------------------------------------------------------*/
nbits = (StereoNbits[brMode] + (2*nbits_bwe))/4; // exclude sum side's low freq
signal_type = param[0];
/*----------------------------------------------------------*
* Encode the high band parameters *
*----------------------------------------------------------*/
k = 0;
if (signal_type == 0) // smooth type
{
prm = param + 17; // skip to AVQ param
n_pack = 4;
nbits_AVQ[0] = ((StereoNbits[brMode])/4)-1-4-3-5-5; //
nbits_AVQ[1] = ((StereoNbits[brMode])/4)-1-7-5-5;
nbits_AVQ[2] = ((StereoNbits[brMode])/4)-5-5;
nbits_AVQ[3] = ((StereoNbits[brMode])/4)-5-5;
AVQ_encmux(n_pack, prm+1, prm_AVQ, nbits_AVQ, low_freq_len_l/8);
/* set pointer to bit stream */
ptr = serial + (k+1)*nbits_pack - nbits;
/* encode first 20 ms frame */
int2bin(param[0], 1, ptr); ptr += 1; // signal type
int2bin(param[1], 4, ptr); ptr += 4; // 1st FIR coef
int2bin(param[2], 3, ptr); ptr += 3; // 2nd FIR coef
int2bin(param[9], 5, ptr); ptr += 5; // 1st mid-freq's gain
int2bin(param[10], 5, ptr); ptr += 5; // 2nd mid-freq's gain
j = unpack4bits_d(nbits_AVQ[0], prm_AVQ, ptr); // AVQ
/* set pointer to bit stream */
ptr = serial + (k+2)*nbits_pack - nbits;
/* encode second 20 ms frame */
*ptr = 0; ptr += 1; // unused bits
int2bin(param[17], 7, ptr); ptr += 7; // global gain
int2bin(param[11], 5, ptr); ptr += 5; // 3rd mid-freq's gain
int2bin(param[12], 5, ptr); ptr += 5; // 4th mid-freq's gain
j += unpack4bits_d(nbits_AVQ[1], prm_AVQ+j, ptr);
/* set pointer to bit stream */
ptr = serial + (k+3)*nbits_pack - nbits;
/* encode third 20 ms frame */
int2bin(param[13], 5, ptr); ptr += 5; // 5th mid-freq's gain
int2bin(param[14], 5, ptr); ptr += 5; // 6th mid-freq's gain
j += unpack4bits_d(nbits_AVQ[2], prm_AVQ+j, ptr);
/* set pointer to bit stream */
ptr = serial + (k+4)*nbits_pack - nbits;
/* encode forth 20 ms frame */
int2bin(param[15], 5, ptr); ptr += 5; // 7th mid-freq's gain
int2bin(param[16], 5, ptr); ptr += 5; // 8th mid-freq's gain
unpack4bits_d(nbits_AVQ[3], prm_AVQ+j, ptr);
}
else // quick type
{
// side information
// 1st packet
/* set pointer to bit stream */
k = 0;
ptr = serial + (k+1)*nbits_pack - nbits;
int2bin(param[0], 1, ptr); ptr += 1; // signal type
if (newStereo->bitrate < 32.0f)
{
int2bin(param[1], 4, ptr); ptr += 4; // 1st FIR coef
}
else
{
int2bin(param[1], 4, ptr); ptr += 4; // 1st FIR coef
int2bin(param[2], 3, ptr); ptr += 3; // 2nd FIR coef
}
int2bin(param[9], 5, ptr); ptr += 5; // 1st mid-freq's gain
int2bin(param[10], 5, ptr); ptr += 5; // 2nd mid-freq's gain
k = 1;
ptr = serial + (k+1)*nbits_pack - nbits;
*ptr = 0; ptr += 1; // reserved bits
if (newStereo->bitrate < 32.0f)
{
int2bin(param[3], 4, ptr); ptr += 4; // 1st FIR coef
}
else
{
int2bin(param[3], 4, ptr); ptr += 4; // 1st FIR coef
int2bin(param[4], 3, ptr); ptr += 3; // 2nd FIR coef
}
int2bin(param[11], 5, ptr); ptr += 5; // 3rd mid-freq's gain
int2bin(param[12], 5, ptr); ptr += 5; // 4th mid-freq's gain
// 3rd packet
k = 2;
ptr = serial + (k+1)*nbits_pack - nbits;
*ptr = 0; ptr += 1; // reserved bits
if (newStereo->bitrate < 32.0f)
{
int2bin(param[5], 4, ptr); ptr += 4; // 1st FIR coef
}
else
{
int2bin(param[5], 4, ptr); ptr += 4; // 1st FIR coef
int2bin(param[6], 3, ptr); ptr += 3; // 2nd FIR coef
}
int2bin(param[13], 5, ptr); ptr += 5; // 5th mid-freq's gain
int2bin(param[14], 5, ptr); ptr += 5; // 6th mid-freq's gain
k = 3;
ptr = serial + (k+1)*nbits_pack - nbits;
*ptr = 0; ptr += 1; // reserved bits
if (newStereo->bitrate < 32.0f)
{
int2bin(param[7], 4, ptr); ptr += 4; // 1st FIR coef
}
else
{
int2bin(param[7], 4, ptr); ptr += 4; // 1st FIR coef
int2bin(param[8], 3, ptr); ptr += 3; // 2nd FIR coef
}
int2bin(param[15], 5, ptr); ptr += 5; // 7th mid-freq's gain
int2bin(param[16], 5, ptr); ptr += 5; // 8th mid-freq's gain
if (newStereo->bitrate < 32.0f)
{
si_bits = 15;
}
else
{
si_bits = 18;
}
prm = param + 17; // 17 side info used
// core (SplitVQ + global gain)
for (k = 0; k < 4; k++) // 4 packets
{
n_pack = 1;
nbits_AVQ[0] = ((StereoNbits[brMode])/4) - si_bits - 7; // 7 global gain
AVQ_encmux(n_pack, prm+1, prm_AVQ, nbits_AVQ, low_freq_len_s/8);
/* set pointer to bit stream */
ptr = serial + (k+1)*nbits_pack - nbits + si_bits;
int2bin(prm[0], 7, ptr); ptr += 7; // global gain
unpack4bits_d(nbits_AVQ[0], prm_AVQ, ptr);
ptr += nbits_AVQ[0];
prm += (1+(low_freq_len_s+low_freq_len_s/8));
}
}
return;
}
/* END_NEW_STEREO */
/* FROM TOP OF THIS FILE */