Files
rtphone/src/libs/libevs/lib_com/window_ola.cpp
2020-06-15 15:41:54 +03:00

437 lines
14 KiB
C++

/*====================================================================================
EVS Codec 3GPP TS26.443 Nov 13, 2018. Version 12.11.0 / 13.7.0 / 14.3.0 / 15.1.0
====================================================================================*/
#include <math.h>
#include "options.h"
#include "cnst.h"
#include "rom_com.h"
#include "prot.h"
/*--------------------------------------------------------------------------
* window_ola()
*
* Windowing, Overlap and Add
*--------------------------------------------------------------------------*/
void window_ola(
const float *ImdctOut, /* i : input */
float *auOut, /* o : output audio */
float *OldauOut, /* i/o: audio from previous frame */
const short L, /* i : length */
const short right_mode,
const short left_mode, /* window overlap of current frame (0: full, 2: none, or 3: half) */
const short use_bfi_win, /* i : use BFI windowing */
const short oldHqVoicing, /* i : previous HqVoicing */
float *oldgapsynth /* i : previous gapsynth */
)
{
short i, decimate, decay;
short n ,n16, windecay48, windecay16;
float win_right[R2_48];
float win_int_left[R1_16];
float win_left[R1_48];
float win_int_right[R2_16];
float SS2[L_FRAME48k-NS2SA(48000, N_ZERO_MDCT_NS)];
float wret2[L_FRAME48k-NS2SA(48000, N_ZERO_MDCT_NS)];
float *paout;
n = (short)((float)L*N_ZERO_MDCT_NS/FRAME_SIZE_NS);
n16 = (short)((float)L_FRAME16k*N_ZERO_MDCT_NS/FRAME_SIZE_NS);
windecay48 = (short)(2*((float)L_FRAME48k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_48;
windecay16 = (short)(2*((float)L_FRAME16k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_16;
decimate = 1;
decay = 0;
tcx_get_windows_mode1( left_mode, right_mode, win_left, win_right, win_int_left, win_int_right, L);
if ( L == L_FRAME32k || L == L_FRAME16k )
{
decimate = 3;
decay = 1;
}
else if ( L == L_FRAME8k )
{
decimate = 6;
decay = 2;
}
else if (L == 512)
{
windecay48 = (short)(2*((float)512*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_25;
decimate = 1;
decay = 0;
}
else if (L== 256)
{
windecay48 = (short)(2*((float)512*N_ZERO_MDCT_NS/FRAME_SIZE_NS))+R1_25;
decimate = 2;
decay = 0;
}
paout=auOut-n;
if( use_bfi_win )
{
if ( L == L_FRAME32k )
{
for (i = 0; i < L/2; i+=2)
{
wret2[L/2-n + i +1] = win_left[(L_FRAME16k/2-i/2-1)*decimate+decay];
wret2[L/2-n + i] = win_int_left[(L_FRAME16k/2-i/2-1)];
}
for (i = n; i < L/2; i+=2)
{
wret2[ i -n] = win_left[(L_FRAME16k-i/2)*decimate-decay-1];
wret2[ i +1-n] = win_int_left[L_FRAME16k-(i/2)-1];
}
}
else
{
for (i = 0; i < L/2; i++)
{
wret2[i+L/2-n] = win_left[(L/2-i-1)*decimate+decay];
}
for (i =n; i < L/2; i++)
{
wret2[i-n] = win_left[(L-i)*decimate-decay-1];
}
}
sinq(EVS_PI/(2*(L-n)), EVS_PI/(4*(L-n)), L-n, SS2);
for (i = n; i < L/2; i++)
{
paout[i] = ImdctOut[L/2 + i];
}
for (i = 0; i < L/2; i++)
{
paout[L/2 + i] = -ImdctOut[L - 1 - i];
}
if( oldHqVoicing )
{
for (i=0 ; i < L-n; i++)
{
auOut[i] = auOut[i]*SS2[i]+ oldgapsynth[i+n]*(SS2[L-n-i-1]);
}
}
else
{
for (i=0 ; i < L-n; i++)
{
auOut[i] =auOut[i]*SS2[i]+ OldauOut[i+n]*(SS2[L-n-i-1])/(wret2[i]+0.01f);
}
}
}
if ( L == L_FRAME32k )
{
if (use_bfi_win==0)
{
for (i = n; i < L/2; i+=2)
{
paout[i] = ImdctOut[L/2 + i] * win_right[(2*L_FRAME16k-(n16+(i-n)/2))*decimate-1-decay-windecay48]+OldauOut[i];
paout[i+1] = ImdctOut[L/2 + i +1] * win_int_right[2*L_FRAME16k-(n16+(i-n)/2)-1-windecay16]+OldauOut[i+1];
}
for (i = 0; i < L/2-n; i+=2)
{
paout[L/2 + i +1] = -ImdctOut[L - 1 - (i+1)] * win_right[(3*L_FRAME16k/2-1-i/2)*decimate+decay-windecay48]+OldauOut[i+L/2+1];
paout[L/2 + i ] = -ImdctOut[L - 1 - i] * win_int_right[(3*L_FRAME16k/2-1-i/2)-windecay16]+OldauOut[i+L/2];
}
for (i = L/2-n; i < L/2; i+=2)
{
paout[L/2 + i +1] = -ImdctOut[L - 1 - (i+1)]+OldauOut[i+L/2+1] ;
paout[L/2 + i ] = -ImdctOut[L - 1 - i]+OldauOut[i+L/2];
}
}
for (i = 0; i < L/2; i+=2)
{
OldauOut[L/2 + i +1] = -ImdctOut[i+1] * win_left[(L_FRAME16k/2-i/2-1)*decimate+decay];
OldauOut[L/2 + i] = -ImdctOut[i] * win_int_left[(L_FRAME16k/2-i/2-1)];
}
for (i = n; i < L/2; i+=2)
{
OldauOut[ i] = -ImdctOut[L/2 - 1 - i] *win_left[(L_FRAME16k-i/2)*decimate-decay-1];
OldauOut[ i +1] = -ImdctOut[L/2 - 1 - (i +1)] * win_int_left[L_FRAME16k-(i/2)-1];
}
}
else
{
if (use_bfi_win==0)
{
for (i = n; i < L/2; i++)
{
paout[i] = ImdctOut[L/2 + i] * win_right[(2*L-i)*decimate-1-decay-windecay48]+OldauOut[i];
}
for (i = 0; i < L/2-n; i++)
{
paout[L/2 + i] = -ImdctOut[L - 1 - i] * win_right[(3*L/2-1-i)*decimate+decay-windecay48]+OldauOut[i+L/2];
}
for (i = L/2-n; i < L/2; i++)
{
paout[L/2 + i] = -ImdctOut[L - 1 - i] + OldauOut[i+L/2];
}
}
for (i = 0; i < L/2; i++)
{
OldauOut[L/2 + i] = -ImdctOut[i] * win_left[(L/2-i-1)*decimate+decay];
}
for (i = n; i < L/2; i++)
{
OldauOut[ i] = -ImdctOut[L/2 - 1 - i] * win_left[(L-i)*decimate-decay-1];
}
}
for (i = 0; i < n; i++)
{
OldauOut[i] = -ImdctOut[L/2 - 1 - i];
}
for (i = 0; i < n; i++)
{
paout[L + i] = OldauOut[i];
}
return;
}
/*---------------------------------------------------------------------*
* core_switching_OLA()
*
* modify window after HQ core decoding
* Overlap ACELP and HQ
*---------------------------------------------------------------------*/
void core_switching_OLA(
const float *mem_over_hp, /* i : upsampling filter memory */
const short last_L_frame, /* i : last L_frame lengthture */
const int output_Fs, /* i : output sampling rate */
float *synth, /* i/o: synthesized signal from HQ core */
const float *synth_subfr_out, /* i : synthesized signal from ACELP core */
float *synth_subfr_bwe, /* i : synthesized BWE from ACELP core */
const short output_frame, /* i : output frame length */
const short bwidth /* i : output bandwidth */
)
{
short i, L, Loverlapp, out_filt_length, filt_delay, decimate, decay;
float tmp_buf_switch[SWITCH_MAX_GAP], tmp_buf_switch2[HQ_DELAY_COMP*HQ_DELTA_MAX+2];
float delta;
const float *win, *win_int;
win = window_48kHz;
win_int = window_8_16_32kHz;
decimate = 1;
decay = 0;
if( output_frame == L_FRAME32k || output_frame == L_FRAME16k )
{
decimate = 3;
decay = 1;
}
else if( output_frame == L_FRAME8k )
{
decimate = 6;
decay = 2;
}
/* set multiplication factor according to the sampling rate */
delta = 1;
if( output_frame == L_FRAME16k )
{
delta = 2;
}
else if( output_frame == L_FRAME32k )
{
delta = 4;
}
else if( output_frame == L_FRAME48k )
{
delta = 6;
}
set_f( tmp_buf_switch, 0, SWITCH_MAX_GAP );
set_f( tmp_buf_switch2, 0, HQ_DELAY_COMP*HQ_DELTA_MAX+2);
Loverlapp = (short)(delta*SWITCH_OVERLAP_8k);
mvr2r( synth_subfr_out,tmp_buf_switch, NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS)); /* copy 6.25 ms subframe */
/* conversion from 12.8kHz to output_Fs */
if( last_L_frame == L_FRAME)
{
/* resample filter memory */
if( output_frame == L_FRAME8k )
{
mvr2r( synth_subfr_out + NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS), tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS),NS2SA(output_Fs, DELAY_CLDFB_NS)); /* copy subframe to tmp buffer */
}
else
{
out_filt_length = modify_Fs_intcub3m_sup( mem_over_hp+2, NS2SA(12800,DELAY_CLDFB_NS), 12800, tmp_buf_switch2, output_Fs , &filt_delay );
for( i=0; i<filt_delay; i++ )
{
tmp_buf_switch2[out_filt_length+i-filt_delay] = tmp_buf_switch2[out_filt_length-1-filt_delay];
}
if ( (bwidth == NB && output_Fs>=16000) || (bwidth > NB && output_Fs>16000) )
{
/* mix cubic and CLDFB resampled buffers in case of resampling to higher frequency rates */
for(i=0; i<out_filt_length; i++)
{
float a = (float) i / out_filt_length;
float b = 1.f - a;
tmp_buf_switch[NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS) + i] = a * tmp_buf_switch2[i] + b * synth_subfr_out[NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS) + i];
}
}
else
{
/* copy cubic resampled buffer (memory) */
mvr2r( tmp_buf_switch2, tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS), out_filt_length );
}
}
}
else
{
if( output_frame == L_FRAME16k )
{
/* no resampling */
mvr2r( mem_over_hp+2, tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS), NS2SA(output_Fs,DELAY_CLDFB_NS) );
}
else
{
if( output_frame == L_FRAME8k )
{
mvr2r( synth_subfr_out+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS), tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS), NS2SA(output_Fs, DELAY_CLDFB_NS)); /* copy subframe to tmp buffer */
}
else
{
/* resample filter memory */
out_filt_length = modify_Fs_intcub3m_sup( mem_over_hp+2, NS2SA(16000,DELAY_CLDFB_NS), 16000, tmp_buf_switch2, output_Fs, &filt_delay );
for( i=0; i<filt_delay; i++ )
{
tmp_buf_switch2[out_filt_length+i-filt_delay] = tmp_buf_switch2[out_filt_length-1-filt_delay];
}
if ( (bwidth == NB && output_Fs>=16000) || (bwidth > NB && output_Fs>16000) )
{
/* mix cubic and CLDFB resampled buffers in case of resampling to higher frequency rates */
for(i=0; i<out_filt_length; i++)
{
float a = (float) i / out_filt_length;
float b = 1.f - a;
tmp_buf_switch[NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS) + i] = a * tmp_buf_switch2[i] + b * synth_subfr_out[NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS) + i];
}
}
else
{
/* copy cubic resampled buffer (memory) */
mvr2r( tmp_buf_switch2, tmp_buf_switch+NS2SA(output_Fs,SWITCH_GAP_LENGTH_NS), out_filt_length );
}
}
}
}
/* Windowing for overlapadd */
L = NS2SA(output_Fs, SWITCH_GAP_LENGTH_NS + DELAY_CLDFB_NS); /* 6.25 ms gap + 1.25 ms resamp */
set_f( synth, 0, L - Loverlapp);
if( output_frame == L_FRAME32k )
{
for( i=0; i<NS2SA(output_Fs,10000000.0f-N_ZERO_MDCT_NS); i+=2 )
{
synth[L-Loverlapp+i] /= win[(3*L_FRAME16k/2-1-i/2)*decimate+decay-(short)(2*((float)L_FRAME48k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))];
synth[L-Loverlapp+i+1] /= win_int[(3*L_FRAME16k/2-1-i/2)-(short)(2*((float)L_FRAME16k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))];
}
}
else
{
for( i=0 ; i<NS2SA(output_Fs,10000000.0f-N_ZERO_MDCT_NS); i++ )
{
synth[L-Loverlapp+i] /= win[(3*output_frame/2-1-i)*decimate+decay-(short)(2*((float)L_FRAME48k*N_ZERO_MDCT_NS/FRAME_SIZE_NS))];
}
}
for( i=0; i<Loverlapp; i++ ) /* Windowing for overlapadd */
{
synth[i+(short)(L-Loverlapp)] *= (float)sin((i+1)*EVS_PI/(2*(Loverlapp+1)));
synth_subfr_bwe[i+(short)(L-Loverlapp)-NS2SA(output_Fs,DELAY_CLDFB_NS)] *= (float)cos((i+1)*EVS_PI/(2*(Loverlapp+1)))*(float)cos((i+1)*EVS_PI/(2*(Loverlapp+1)));
tmp_buf_switch[i+(short)(L-Loverlapp)] *= (float)cos((i+1)*EVS_PI/(2*(Loverlapp+1)))*(float)cos((i+1)*EVS_PI/(2*(Loverlapp+1)));
}
/* overlap-add ACELP (tmp_buf_switch) + HQ (synth) */
for( i=0; i<NS2SA(output_Fs,DELAY_CLDFB_NS); i++ )
{
synth[i] += tmp_buf_switch[i];
}
for( i=NS2SA(output_Fs,DELAY_CLDFB_NS); i<L; i++ )
{
synth[i]+= tmp_buf_switch[i] + synth_subfr_bwe[i-NS2SA(output_Fs,DELAY_CLDFB_NS)];
}
return;
}
/*-------------------------------------------------------------------*
* sinq()
*
* Fast sinus generate sin(tmp*i+phi)
*-------------------------------------------------------------------*/
void sinq(
const float tmp, /* i : sinus factor cos(tmp*i+phi) */
const float phi, /* i : sinus phase cos(tmp*i+phi) */
const short N, /* i : size of output */
float x[] /* o : output vector */
)
{
float A;
short i;
x[0] = (float)sin(phi);
x[1] = (float)sin(tmp+phi);
x[2] = (float)sin(2*tmp+phi);
if (fabs((float)(tmp)) > 0.0001f)
{
A = (x[2]+x[0])/x[1];
}
else
{
A = 0;
}
for (i=3; i<N; i++)
{
x[i] = A*x[i-1]-x[i-2];
}
return;
}