/*====================================================================================
EVS Codec 3GPP TS26.442 Jun 30, 2015. Version CR 26.442-0010
====================================================================================*/
/*!
\file
\brief Complex cldfb analysis/synthesis, $Revision: 1214 $
This module contains the cldfb filterbank for analysis [ cplxAnalysisCldfbFiltering() ] and
synthesis [ cplxSynthesisCldfbFiltering() ]. It is a polyphase implementation of a complex
exponential modulated filter bank. The analysis part usually runs at half the sample rate
than the synthesis part. (So called "dual-rate" mode.)
\anchor PolyphaseFiltering
About polyphase filtering
The polyphase implementation of a filterbank requires filtering at the input and output.
This is implemented as part of cplxAnalysisCldfbFiltering() and cplxSynthesisCldfbFiltering().
*/
#include "stl.h"
#include "cnst_fx.h"
#include "stat_com.h"
#include "rom_com_fx.h"
#include "basop_util.h"
#include "prot_fx.h"
#include
#define STATE_BUFFER_SIZE ( 9+16 )
#define CLDFB_NO_POLY ( 5 )
#define SYN_FILTER_HEADROOM ( 1 )
#define CLDFB_LDCLDFB_PFT_SCALE ( 0 )
#define CLDFB_CLDFB80_O24_PFT_SCALE ( 1 )
#define CLDFB_CLDFB80_O5_PFT_SCALE ( 1 )
#define CLDFB_CLDFB80_PFT_SCALE ( 1 )
#define SYN_FILTER_HEADROOM_1MS ( 2 )
#define SYN_FILTER_HEADROOM_2MS ( 2 )
#define SYN_FILTER_HEADROOM_2_5MS ( 2 )
#define SYN_FILTER_HEADROOM_8MS ( 1 )
#define N8 ( 4 )
#define N10 ( 5 )
#define N16 ( 8 )
#define N20 ( 10 )
#define N30 ( 15 )
#define N32 ( 16 )
#define N40 ( 20 )
#define N60 ( 30 )
static void
cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs);
#define cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi) zr = L_sub(Mpy_32_16_1(*xr,*cr), Mpy_32_16_1(*xi,*ci)); \
zi = L_add(Mpy_32_16_1(*xr,*ci), Mpy_32_16_1(*xi,*cr)); \
*yr = zr; move32(); \
*yi = zi; move32(); \
yr+=syr, yi+=syi, xr+=sxr, xi+=sxi, cr++, ci++
#define cplxMpy(ryr,ryi,iyr,iyi,rxr,rxi,ixr,ixi,cr,ci,g,sx,sr) ryr = Mpy_32_16_1(L_sub(Mpy_32_16_1(*rxr,*cr),Mpy_32_16_1(*rxi,*ci)),g); \
ryi = Mpy_32_16_1(L_add(Mpy_32_16_1(*rxr,*ci),Mpy_32_16_1(*rxi,*cr)),g); \
iyr = Mpy_32_16_1(L_sub(Mpy_32_16_1(*ixr,*cr),Mpy_32_16_1(*ixi,*ci)),g); \
iyi = Mpy_32_16_1(L_add(Mpy_32_16_1(*ixr,*ci),Mpy_32_16_1(*ixi,*cr)),g); \
rxr+=sx, rxi+=sx, ixr+=sx, ixi+=sx, cr+=sr, ci+=sr
#define add1(y1,y2,y3,y4,rr12,ri12,ir12,ii12,s) *y1 = round_fx(L_shl(L_negate(L_add(rr12,ii12)),s)); \
*y2 = round_fx(L_shl(L_negate(L_add(ri12,ir12)),s)); \
*y3 = round_fx(L_shl(L_sub(rr12,ii12),s)); \
*y4 = round_fx(L_shl(L_sub(ir12,ri12),s)); \
y1+=2, y2-=2, y3-=2, y4+=2
#define add2(y1,y2,y3,y4,rr12,ri12,ir12,ii12,s) *y1 = round_fx(L_shl(L_add(ri12,ir12),s)); \
*y2 = round_fx(L_shl(L_add(rr12,ii12),s)); \
*y3 = round_fx(L_shl(L_sub(ir12,ri12),s)); \
*y4 = round_fx(L_shl(L_sub(rr12,ii12),s)); \
y1+=2, y2-=2, y3-=2, y4+=2
#define ptrUpdate16(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22) \
y11 += 2*N8, y12 -= 2*N8, y13 -= 2*N8, y14 += 2*N8, r11 -= 1*N8; \
x11 -= 2*N8, x12 -= 2*N8, x13 -= 2*N8, x14 -= 2*N8, r12 -= 1*N8; \
y21 += 2*N8, y22 -= 2*N8, y23 -= 2*N8, y24 += 2*N8, r21 += 1*N8; \
x21 += 2*N8, x22 += 2*N8, x23 += 2*N8, x24 += 2*N8, r22 += 1*N8
#define ptrUpdate20(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22) \
y11 += 2*N10, y12 -= 2*N10, y13 -= 2*N10, y14 += 2*N10, r11 -= 1*N10; \
x11 -= 2*N10, x12 -= 2*N10, x13 -= 2*N10, x14 -= 2*N10, r12 -= 1*N10; \
y21 += 2*N10, y22 -= 2*N10, y23 -= 2*N10, y24 += 2*N10, r21 += 1*N10; \
x21 += 2*N10, x22 += 2*N10, x23 += 2*N10, x24 += 2*N10, r22 += 1*N10
static void cplxMult10(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
Word32 zr, zi;
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
}
static void cplxMult16(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
Word32 zr, zi;
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,zr,zi);
}
static void cplxMult20(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
cplxMult10(&yr[0*N10*syr], &yi[0*N10*syi], &xr[0*N10*sxr], &xi[0*N10*sxi], &cr[0*N10], &ci[0*N10], syr, syi, sxr, sxi);
cplxMult10(&yr[1*N10*syr], &yi[1*N10*syi], &xr[1*N10*sxr], &xi[1*N10*sxi], &cr[1*N10], &ci[1*N10], syr, syi, sxr, sxi);
}
static void cplxMult30(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
cplxMult10(&yr[0*N10*syr], &yi[0*N10*syi], &xr[0*N10*sxr], &xi[0*N10*sxi], &cr[0*N10], &ci[0*N10], syr, syi, sxr, sxi);
cplxMult10(&yr[1*N10*syr], &yi[1*N10*syi], &xr[1*N10*sxr], &xi[1*N10*sxi], &cr[1*N10], &ci[1*N10], syr, syi, sxr, sxi);
cplxMult10(&yr[2*N10*syr], &yi[2*N10*syi], &xr[2*N10*sxr], &xi[2*N10*sxi], &cr[2*N10], &ci[2*N10], syr, syi, sxr, sxi);
}
static void cplxMult32(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
cplxMult16(&yr[0*N16*syr], &yi[0*N16*syi], &xr[0*N16*sxr], &xi[0*N16*sxi], &cr[0*N16], &ci[0*N16], syr, syi, sxr, sxi);
cplxMult16(&yr[1*N16*syr], &yi[1*N16*syi], &xr[1*N16*sxr], &xi[1*N16*sxi], &cr[1*N16], &ci[1*N16], syr, syi, sxr, sxi);
}
static void cplxMult40(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
cplxMult20(&yr[0*N20*syr], &yi[0*N20*syi], &xr[0*N20*sxr], &xi[0*N20*sxi], &cr[0*N20], &ci[0*N20], syr, syi, sxr, sxi);
cplxMult20(&yr[1*N20*syr], &yi[1*N20*syi], &xr[1*N20*sxr], &xi[1*N20*sxi], &cr[1*N20], &ci[1*N20], syr, syi, sxr, sxi);
}
static void cplxMult60(Word32 *yr, Word32 *yi, Word32 *xr, Word32 *xi, const Word16 *cr, const Word16 *ci, Word16 syr, Word16 syi, Word16 sxr, Word16 sxi)
{
cplxMult30(&yr[0*N30*syr], &yi[0*N30*syi], &xr[0*N30*sxr], &xi[0*N30*sxi], &cr[0*N30], &ci[0*N30], syr, syi, sxr, sxi);
cplxMult30(&yr[1*N30*syr], &yi[1*N30*syi], &xr[1*N30*sxr], &xi[1*N30*sxi], &cr[1*N30], &ci[1*N30], syr, syi, sxr, sxi);
}
static void cplxMultAdd10_1(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4,
Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI,
const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s,
Word16 sx, Word16 sr)
{
Word32 rr12, ri12, ir12, ii12;
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
}
static void cplxMultAdd10_2(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4,
Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI,
const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s,
Word16 sx, Word16 sr)
{
Word32 rr12, ri12, ir12, ii12;
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
}
static void cplxMultAdd20_1(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4,
Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI,
const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s,
Word16 sx, Word16 sr)
{
Word32 rr12, ri12, ir12, ii12;
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
}
static void cplxMultAdd20_2(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4,
Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI,
const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s,
Word16 sx, Word16 sr)
{
Word32 rr12, ri12, ir12, ii12;
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr);
add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s);
}
/* calcModulation
Parameters:
*rYR O: pointer to real output samples (DST)
*rYI O: pointer to imaginary output samples (DST)
*rXR I: pointer to real input samples (DST)
*rXI I: pointer to imaginary input samples (DST)
srYR I: offset for update of pointer to real output samples (DST)
srYI I: offset for update of pointer to imaginary output samples (DST)
srXR I: offset for update of pointer to real input samples (DST)
srXI I: offset for update of pointer to imaginary input samples (DST)
*iYR O: pointer to real output samples (DCT)
*iYI O: pointer to imaginary output samples (DCT)
*iXR I: pointer to real input samples (DCT)
*iXI I: pointer to imaginary input samples (DCT)
siYR I: offset for update of pointer to real output samples (DCT)
siYI I: offset for update of pointer to imaginary output samples (DCT)
siXR I: offset for update of pointer to real input samples (DCT)
siXI I: offset for update of pointer to imaginary input samples (DCT)
m I: processed cldfb bands
Function:
The function applies for each cldfb length a unrolled complex modulation
Returns:
void
*/
static void calcModulation( Word32 *rYR,
Word32 *rYI,
Word32 *rXR,
Word32 *rXI,
Word16 srYR,
Word16 srYI,
Word16 srXR,
Word16 srXI,
Word32 *iYR,
Word32 *iYI,
Word32 *iXR,
Word32 *iXI,
Word16 siYR,
Word16 siYI,
Word16 siXR,
Word16 siXI,
const Word16 *rRotVctr,
const Word16 *iRotVctr,
Word16 m
)
{
SWITCH (m)
{
case 10:
cplxMult10(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult10(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
case 16:
cplxMult16(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult16(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
case 20:
cplxMult20(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult20(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
case 32:
cplxMult32(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult32(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
case 40:
cplxMult40(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult40(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
case 60:
cplxMult60(rYR, rYI, rXR, rXI, rRotVctr, iRotVctr, srYR, srYI, srXR, srXI);
cplxMult60(iYR, iYI, iXR, iXI, rRotVctr, iRotVctr, siYR, siYI, siXR, siXI);
BREAK;
default:
assert(0);
}
}
/* calcModulationAndFolding
Parameters:
*rY O: pointer to folded samples (DST + DCT)
*rX I: pointer to real input samples (DST)
*iX I: pointer to imaginary input samples (DCT)
*rRotVctr I: pointer to real modulation coefficients
*iRotVctr I: pointer to imaginary modulation coefficients
gain I: gain value
scale I: scale factor
m I: processed cldfb bands
m2 I: half of processed cldfb bands
Function:
The function applies for each cldfb length a unrolled complex modulation with subsequent data folding
Returns:
void
*/
static void calcModulationAndFolding( Word16 *rY,
Word32 *rX,
Word32 *iX,
const Word16 *rRotVctr,
const Word16 *iRotVctr,
Word16 gain,
Word16 scale,
Word16 m,
Word16 m2
)
{
Word16 *y11, *y12, *y13, *y14;
Word16 *y21, *y22, *y23, *y24;
Word32 *x11, *x12, *x13, *x14;
Word32 *x21, *x22, *x23, *x24;
const Word16 *r11, *r12, *r21, *r22;
y11 = &rY[m+m2+1];
y12 = &rY[m2-2];
y13 = &rY[m+m2-2];
y14 = &rY[m2+1];
y21 = &rY[m+m2];
y22 = &rY[m2-1];
y23 = &rY[m+m2-1];
y24 = &rY[m2];
x11 = &rX[m-2];
x12 = &rX[m-1];
x13 = &iX[m-2];
x14 = &iX[m-1];
x21 = &rX[0];
x22 = &rX[1];
x23 = &iX[0];
x24 = &iX[1];
r11 = &rRotVctr[m2-1];
r12 = &iRotVctr[m2-1];
r21 = &rRotVctr[0];
r22 = &iRotVctr[0];
SWITCH (m)
{
case 10:
cplxMultAdd10_1(y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1);
cplxMultAdd10_2(y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1);
BREAK;
case 20:
cplxMultAdd20_1(y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1);
cplxMultAdd20_2(y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1);
BREAK;
case 60:
cplxMultAdd20_1(y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1);
cplxMultAdd20_2(y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1);
ptrUpdate20(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22);
/* no break */
case 40:
cplxMultAdd20_1(y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1);
cplxMultAdd20_2(y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1);
ptrUpdate20(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22);
cplxMultAdd20_1(y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1);
cplxMultAdd20_2(y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1);
ptrUpdate20(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22);
BREAK;
default:
assert(0);
}
}
/* cldfbAnalysisFiltering
Parameters:
cldfbBank I/O: handle to analysis CLDFB filter struct
**rAnalysis O: matrix holding the real part of the subband samples
**iAnalysis O: matrix holding the imaginary part of the subband samples
*scaleFactor O: pointer to cldfb scalefactor struct
*timeIn I: pointer to time domain data
stride I: stride for time domain data
*pWorkBuffer I: pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32
Function:
Performs complex-valued subband filtering of the time domain data of timeIn and stores the real
part of the subband samples in rAnalysis, and the imaginary part in iAnalysis
Returns:
void
*/
void cldfbAnalysisFiltering( HANDLE_CLDFB_FILTER_BANK cldfbBank,
Word32 **rAnalysis,
Word32 **iAnalysis,
CLDFB_SCALE_FACTOR *scaleFactor,
const Word16 *timeIn,
const Word16 timeIn_e,
const Word16 nTimeSlots,
Word32 *pWorkBuffer
)
{
Word16 i,k;
Word16 L2,L3,L4,m,m2,M4;
Word16 M0M2,M2M1,L3M1,L4M1;
Word16 scale;
Word16 offset;
Word16 p_stride;
Word16 nSamples;
Word16 nSamplesUpd;
Word16 stride;
Word32 r1,r2;
Word32 i1,i2;
Word32 *rBuffer;
Word32 *iBuffer;
Word16 *pStates;
Word16 *pStates1;
Word16 *pStates2;
Word16 *pStates3;
Word16 *pStates4;
Word16 *pStates6;
Word16 *pStates5;
const Word16 *rRotVctr;
const Word16 *iRotVctr;
const Word16 *pFilter;
const Word16 *pFilter1;
const Word16 *pFilter2;
const Word16 *pFilter3;
const Word16 *pFilter4;
const Word16 *pFilter6;
const Word16 *pFilter5;
Word32 workBuffer[2*BASOP_CFFT_MAX_LENGTH];
stride = 1; /* constant */
m = cldfbBank->no_channels;
move16();
L2 = shl(m,1);
m2 = shr(m,1);
M4 = shr(m,2);
M4 = sub(m2,M4);
L3 = sub(L2,m2);
L4 = add(L2,m2);
M0M2 = sub(0,m2);
M2M1 = sub(m2,1);
L3M1 = sub(L3,1);
L4M1 = sub(L4,1);
rBuffer = &pWorkBuffer[0];
iBuffer = &pWorkBuffer[m];
rRotVctr = cldfbBank->rRotVctr;
iRotVctr = cldfbBank->iRotVctr;
pStates = cldfbBank->FilterStates;
pStates1 = &pStates[L3M1];
pStates2 = &pStates[L3];
pStates3 = &pStates[m2];
pStates4 = &pStates[M2M1];
pStates5 = &pStates[L4M1];
pStates6 = &pStates[M0M2];
p_stride = CLDFB_NO_POLY;
pFilter = &cldfbBank->p_filter[p_stride - CLDFB_NO_POLY];
pFilter1 = &pFilter[p_stride*L3M1];
pFilter2 = &pFilter[p_stride*L3];
pFilter3 = &pFilter[p_stride*m2];
pFilter4 = &pFilter[p_stride*M2M1];
pFilter5 = &pFilter[p_stride*L4M1];
pFilter6 = &pFilter[p_stride*M0M2];
nSamples = i_mult(nTimeSlots, cldfbBank->no_channels);
nSamplesUpd = i_mult(cldfbBank->no_col, cldfbBank->no_channels);
offset = sub(sub(cldfbBank->p_filter_length, cldfbBank->no_channels),cldfbBank->zeros);
/* Determine states scale */
scale = -15;
move16();
k = 0;
move16();
FOR (i=0; ino_channels)
{
cldfbBank->FilterStates_e[k] = cldfbBank->FilterStates_e[k+cldfbBank->no_col];
move16();
assert((size_t)k < sizeof(cldfbBank->FilterStates_e)/sizeof(cldfbBank->FilterStates_e[0]));
scale = s_max(scale, cldfbBank->FilterStates_e[k]);
k = add(k,1);
}
FOR (i=0; ino_channels)
{
cldfbBank->FilterStates_e[k] = timeIn_e;
move16();
assert((size_t)k < sizeof(cldfbBank->FilterStates_e)/sizeof(cldfbBank->FilterStates_e[0]));
scale = s_max(scale, cldfbBank->FilterStates_e[k]);
k = add(k,1);
}
i = s_max(scale, timeIn_e);
scale = sub(cldfbBank->FilterStates_eg, i);
cldfbBank->FilterStates_eg = i;
move16();
/* if nTimeSlots==0, make sure we have a value. */
scaleFactor->lb_scale = add(cldfbBank->anaScalefactor, add(cldfbBank->FilterStates_eg, 5));
move16();
/* move and scale filter states */
FOR (i=0; iFilterStates_eg);
FOR (i=0; ilb_scale = add(cldfbBank->anaScalefactor, add(cldfbBank->FilterStates_eg, scale));
move16();
/* FFT of DCT IV */
BASOP_cfft(&iBuffer[0], &iBuffer[1], m2, 2, &scale, workBuffer);
/* post modulation of DST IV and DCT IV */
calcModulation(&rAnalysis[k][m-1], &rAnalysis[k][0], &rBuffer[0], &rBuffer[1],-2, 2, 2, 2,
&iAnalysis[k][0], &iAnalysis[k][m-1], &iBuffer[0], &iBuffer[1], 2,-2, 2, 2,
rRotVctr, iRotVctr, m);
/* update states pointer */
pStates1 = &pStates1[cldfbBank->no_channels];
pStates2 = &pStates2[cldfbBank->no_channels];
pStates3 = &pStates3[cldfbBank->no_channels];
pStates5 = &pStates5[cldfbBank->no_channels];
pStates4 = &pStates4[cldfbBank->no_channels];
pStates6 = &pStates6[cldfbBank->no_channels];
}
}
/* cldfbSynthesisFiltering
Parameters:
cldfbBank I/O: handle to analysis CLDFB filter struct
**rAnalysis I: matrix holding the real part of the subband samples
**iAnalysis I: matrix holding the imaginary part of the subband samples
*scaleFactor I: pointer to cldfb scalefactor struct
ov_len I: determines overlapping area in time slots (obsolete)
*timeOut O: pointer to time domain data
stride I: stride for time domain data
*pWorkBuffer I: pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32 + 2*cldfbbands*Word16
Function:
Performs inverse complex-valued subband filtering of the subband samples in rAnalysis and iAnalysis
and stores the time domain data in timeOut
Returns:
void
*/
void
cldfbSynthesisFiltering( HANDLE_CLDFB_FILTER_BANK cldfbBank,
Word32 **rAnalysis,
Word32 **iAnalysis,
const CLDFB_SCALE_FACTOR *scaleFactor,
Word16 *timeOut,
const Word16 timeOut_e,
const Word16 nTimeSlots,
Word32 *pWorkBuffer
)
{
Word16 i;
Word16 k;
Word16 L2;
Word16 m;
Word16 m2;
Word16 Lz;
Word16 Mz;
Word32 acc;
Word16 offset1;
Word16 offset2;
Word16 channels0;
Word16 channels1;
Word16 channels2;
Word16 channels3;
Word16 channels4;
Word16 statesSizeM1;
Word16 statesSizeM2;
Word16 stride;
Word16 scale, scaleMod;
Word16 outScale;
Word16 scaleLB;
Word16 scaleHB;
Word32 *rAnalysisS;
Word32 *iAnalysisS;
Word32 *rBuffer;
Word32 *iBuffer;
Word16 *nBuffer;
Word16 *pStates;
Word16 *pStatesI;
Word16 *pStatesR;
const Word16 *pFilterS;
const Word16 *pFilterM;
const Word16 *rRotVctr;
const Word16 *iRotVctr;
Word32 workBuffer[2*BASOP_CFFT_MAX_LENGTH];
m = cldfbBank->no_channels;
move16();
L2 = shl(m,1);
m2 = shr(m,1);
Lz = s_min(cldfbBank->lsb, sub(m,cldfbBank->bandsToZero));
Mz = s_min(cldfbBank->usb, sub(m,cldfbBank->bandsToZero));
stride = 1; /* constant */
channels0 = sub(m,cldfbBank->zeros);
channels1 = sub(m,1);
channels2 = shl(m,1);
channels3 = add(m,channels2);
channels4 = shl(channels2,1);
statesSizeM1 = sub(shl(cldfbBank->p_filter_length,1),m);
statesSizeM2 = sub(statesSizeM1,m);
offset1 = sub(channels1,cldfbBank->zeros);
offset2 = add(offset1,cldfbBank->no_channels);
rBuffer = &pWorkBuffer[0];
iBuffer = &pWorkBuffer[m];
nBuffer = (Word16*)(&pWorkBuffer[L2]);
rAnalysisS = &pWorkBuffer[3*m];
iAnalysisS = &pWorkBuffer[4*m];
rRotVctr = cldfbBank->rRotVctr;
iRotVctr = cldfbBank->iRotVctr;
scale = scaleFactor->lb_scale;
move16();
if ( sub(Lz, Mz) != 0 )
{
scale = s_max(scale, scaleFactor->hb_scale);
}
scaleLB = limitScale32(sub(scale, scaleFactor->lb_scale));
scaleHB = limitScale32(sub(scale, scaleFactor->hb_scale));
outScale = cldfbBank->synFilterHeadroom;
move16();
scaleMod = sub(add(scale, cldfbBank->outScalefactor), outScale);
/* Increase CLDFB synthesis states for low level signals */
IF ( sub(scale, 8) < 0)
{
scaleMod = add(scaleMod, 2);
outScale = sub(outScale, 2);
}
scaleMod = sub(scaleMod, timeOut_e);
scale = add(outScale, timeOut_e);
IF ( sub(scale, cldfbBank->FilterStates_eg) != 0)
{
Scale_sig(cldfbBank->FilterStates, statesSizeM2, sub(cldfbBank->FilterStates_eg, scale));
cldfbBank->FilterStates_eg = scale;
move16();
}
FOR (k=0; k < nTimeSlots; k++)
{
{
FOR (i=0; i < Lz; i+=2)
{
rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleLB);
move32();
iAnalysisS[i] = L_negate(L_shr(iAnalysis[k][i],scaleLB));
move32();
}
IF ( sub(i,Mz) < 0 )
{
FOR ( ; i < Mz; i+=2)
{
rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleHB);
move32();
iAnalysisS[i] = L_negate(L_shr(iAnalysis[k][i],scaleHB));
move32();
}
}
IF ( sub(i,m) < 0 )
{
FOR ( ; i < m; i+=2)
{
rAnalysisS[i] = L_deposit_l(0);
iAnalysisS[i] = L_deposit_l(0);
}
}
FOR (i=1; i < Lz; i+=2)
{
rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleLB);
move32();
iAnalysisS[i] = L_shr(iAnalysis[k][i],scaleLB);
move32();
}
IF ( sub(i,Mz) < 0 )
{
FOR ( ; i < Mz; i+=2)
{
rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleHB);
move32();
iAnalysisS[i] = L_shr(iAnalysis[k][i],scaleHB);
move32();
}
}
IF ( sub(i,m) < 0 )
{
FOR ( ; i < m; i+=2)
{
rAnalysisS[i] = L_deposit_l(0);
iAnalysisS[i] = L_deposit_l(0);
}
}
}
/* pre modulation */
calcModulation(&rBuffer[0], &rBuffer[1], &rAnalysisS[0], &rAnalysisS[m-1], 2, 2, 2,-2,
&iBuffer[0], &iBuffer[1], &iAnalysisS[0], &iAnalysisS[m-1], 2, 2, 2,-2,
rRotVctr, iRotVctr, m);
/* FFT of DST IV */
scale = 0;
move16();
BASOP_cfft(&rBuffer[0], &rBuffer[1], m2, 2, &scale, workBuffer);
/* FFT of DCT IV */
scale = scaleMod;
move16();
BASOP_cfft(&iBuffer[0], &iBuffer[1], m2, 2, &scale, workBuffer);
/* post modulation and folding */
calcModulationAndFolding(nBuffer, rBuffer, iBuffer, rRotVctr, iRotVctr, cldfbBank->synGain, scale, m, m2);
/* prototype filter */
pStates = &cldfbBank->FilterStates[k*L2];
pFilterS = &cldfbBank->p_filter[0];
pFilterM = &cldfbBank->p_filter[shr(cldfbBank->p_filter_length,1)];
FOR (i=0; i < channels0; i++)
{
pStatesI = &pStates[i];
pStatesR = &pStates[i+channels3];
acc = L_mult( *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, nBuffer[channels1-i], *pFilterM++);
BASOP_SATURATE_WARNING_OFF
timeOut[(offset1-i)*stride] = round_fx(L_shl(acc,outScale));
BASOP_SATURATE_WARNING_ON
}
FOR ( ; ino_channels; i++)
{
pStatesI = &pStates[i+channels2];
pStatesR = &pStates[i+channels2+channels3];
acc = L_mult( *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
pStatesR += channels4;
pStatesI += channels4;
acc = L_mac(acc, *pStatesI, *pFilterS++);
acc = L_mac(acc, *pStatesR, *pFilterM++);
acc = L_mac(acc, nBuffer[channels1+m-i], *pFilterS++);
pFilterM++;
BASOP_SATURATE_WARNING_OFF
timeOut[(offset2-i)*stride] = round_fx(L_shl(acc,outScale));
BASOP_SATURATE_WARNING_ON
}
FOR (i=0; ino_channels; i++)
{
pStates[statesSizeM1+i] = nBuffer[channels1-i];
move16();
pStates[statesSizeM2+i] = nBuffer[channels1+m-i];
move16();
}
timeOut = &timeOut[m*stride];
}
/* move filter states */
Copy(&cldfbBank->FilterStates[i_mult(nTimeSlots,L2)], cldfbBank->FilterStates, statesSizeM2);
set16_fx(&cldfbBank->FilterStates[statesSizeM2],0,L2);
}
/*-------------------------------------------------------------------*
* configureClfdb()
*
* configures a CLDFB handle
*--------------------------------------------------------------------*/
void configureCldfb ( HANDLE_CLDFB_FILTER_BANK h_cldfb, /*!< Returns handle */
const Word16 no_channels, /*!< Number of channels (bands) */
const Word16 frameSize /*!< FrameSize */
)
{
h_cldfb->no_channels = no_channels;
move16();
assert(h_cldfb->no_channels >= 10);
h_cldfb->no_col = div_l(frameSize,shr(h_cldfb->no_channels,1));
/* was cldfbInitFilterBank()*/
h_cldfb->anaScalefactor = 0;
move16();
h_cldfb->synScalefactor = 0;
move16();
h_cldfb->bandsToZero = 0;
move16();
h_cldfb->filtermode = 0;
move16();
h_cldfb->memory = 0;
move16();
h_cldfb->memory_length = 0;
move16();
h_cldfb->p_filter_length = i_mult(10,h_cldfb->no_channels);
move16();
h_cldfb->flags = s_or(h_cldfb->flags,CLDFB_FLAG_2_5MS_SETUP);
h_cldfb->filterScale = CLDFB_CLDFB80_PFT_SCALE;
move16();
h_cldfb->zeros = 0;
move16();
h_cldfb->synFilterHeadroom = SYN_FILTER_HEADROOM_2_5MS;
move16();
cldfb_init_proto_and_twiddles (h_cldfb);
h_cldfb->lsb = no_channels;
move16();
h_cldfb->usb = s_min(no_channels, h_cldfb->no_channels); /* Does this make any sense? in the previous implemenatation lsb, usb and no_channels are all maxCldfbBands */ move16();
h_cldfb->FilterStates = (void*)h_cldfb->FilterStates;
h_cldfb->outScalefactor = h_cldfb->synScalefactor;
move16();
return;
}
/*-------------------------------------------------------------------*
* openClfdb()
*
* open and configures a CLDFB handle
*--------------------------------------------------------------------*/
void openCldfb ( HANDLE_CLDFB_FILTER_BANK *h_cldfb, /*!< Returns handle */
const Word16 type, /*!< analysis or synthesis */
const Word16 maxCldfbBands, /*!< number of cldfb bands */
const Word16 frameSize /*!< FrameSize */
)
{
HANDLE_CLDFB_FILTER_BANK hs;
hs = (HANDLE_CLDFB_FILTER_BANK) calloc(1, sizeof (struct CLDFB_FILTER_BANK));
hs->type = type;
move16();
IF (type == CLDFB_ANALYSIS)
{
hs->FilterStates = (Word16 *) calloc(STATE_BUFFER_SIZE*maxCldfbBands, sizeof (Word16));
}
ELSE
{
hs->FilterStates = (Word16 *) calloc( 2 * STATE_BUFFER_SIZE * maxCldfbBands, sizeof (Word16));
}
hs->flags &= ~CLDFB_FLAG_KEEP_STATES;
configureCldfb (hs, maxCldfbBands, frameSize );
hs->memory = NULL;
hs->memory_length = 0;
move16();
IF( hs->type == CLDFB_ANALYSIS)
{
test();
IF ( (s_and(hs->flags,CLDFB_FLAG_KEEP_STATES) == 0) && (hs->FilterStates != 0) )
{
set16_fx(hs->FilterStates, 0, i_mult(STATE_BUFFER_SIZE,hs->no_channels));
set16_fx(hs->FilterStates_e, 0, sizeof(hs->FilterStates_e)/sizeof(hs->FilterStates_e[0]));
hs->FilterStates_eg = 0;
move16();
}
}
ELSE IF (hs->type == CLDFB_SYNTHESIS )
{
IF ( hs->FilterStates != 0 )
{
IF ( s_and(hs->flags,CLDFB_FLAG_KEEP_STATES) == 0 )
{
set16_fx(hs->FilterStates, 0, i_mult( shl(STATE_BUFFER_SIZE,1), hs->no_channels));
}
}
hs->FilterStates_eg = 0;
move16();
}
if (h_cldfb != NULL)
{
*h_cldfb = hs;
}
return;
}
/*-------------------------------------------------------------------*
* resampleCldfb()
*
* Change sample rate of filter bank
*--------------------------------------------------------------------*/
void resampleCldfb (HANDLE_CLDFB_FILTER_BANK hs,
const Word16 newCldfbBands,
const Word16 frameSize,
const Word8 firstFrame
)
{
Word16 timeOffset;
Word16 timeOffsetOld;
Word16 noChannelsOld;
noChannelsOld = hs->no_channels;
move16();
timeOffsetOld = sub(sub(hs->p_filter_length,hs->no_channels),hs->zeros);
/* change all CLDFB bank parameters that depend on the no of channels */
hs->flags = s_or(hs->flags,CLDFB_FLAG_KEEP_STATES);
move16();
/* new settings */
configureCldfb (hs, newCldfbBands, frameSize);
/* resample cldfb state buffer */
timeOffset = sub(sub(hs->p_filter_length,hs->no_channels),hs->zeros);
IF( firstFrame == 0 )
{
/*low complexity-resampling only stored previous samples that are needed for next frame modulation */
lerp(hs->FilterStates+(noChannelsOld*hs->no_col), hs->FilterStates+(noChannelsOld*hs->no_col), timeOffset, timeOffsetOld);
Copy(hs->FilterStates+(noChannelsOld*hs->no_col), hs->FilterStates+frameSize, timeOffset);
}
return;
}
/*
AnalysisPostSpectrumScaling_Fx
Parameters:
cldfbBank I: CLDFB handle
**rSubband32 I: matrix holding real part of the CLDFB subsamples
**iSubband32 I: matrix holding imaginary part of the CLDFB subsamples
**rSubband16 O: matrix holding real part of the CLDFB subsamples
**iSubband16 O: matrix holding imaginary part of the CLDFB subsamples
*cldfbScale O: cldfb lowband scalefactor
Function:
performs dynamic spectrum scaling for all subband
Returns:
headroom
*/
Word16
AnalysisPostSpectrumScaling_Fx (HANDLE_CLDFB_FILTER_BANK cldfbBank, /*!< Handle of cldfbBank */
Word32 **rSubband32, /*!< Real bands */
Word32 **iSubband32, /*!< Imaginary bands */
Word16 **rSubband16, /*!< Real bands */
Word16 **iSubband16, /*!< Imaginary bands */
Word16 *cldfbScale /*!< CLDFB lowband scalefactor */
)
{
Word16 i;
Word16 j;
Word16 headRoom;
headRoom = BASOP_util_norm_l_dim2_cplx (
(const Word32 * const*) rSubband32,
(const Word32 * const*) iSubband32,
0,
cldfbBank->no_channels,
0,
cldfbBank->no_col
);
FOR (i=0; i < cldfbBank->no_col; i++)
{
FOR (j=0; j < cldfbBank->no_channels; j++)
{
rSubband16[i][j] = round_fx(L_shl(rSubband32[i][j], headRoom));
iSubband16[i][j] = round_fx(L_shl(iSubband32[i][j], headRoom));
}
}
*cldfbScale = add(*cldfbScale,headRoom);
move16();
return headRoom;
}
/*-------------------------------------------------------------------*
* analysisCLDFBEncoder()
*
* Encoder CLDFB analysis + energy stage
*--------------------------------------------------------------------*/
void analysisCldfbEncoder_fx(
Encoder_State_fx *st_fx, /* i/o: encoder state structure */
const Word16 *timeIn,
Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word32 enerBuffSum[CLDFB_NO_CHANNELS_MAX],
Word16 *enerBuffSum_exp,
CLDFB_SCALE_FACTOR * scale
)
{
Word16 i;
CLDFB_SCALE_FACTOR enerScale;
Word32 *ppBuf_Real[CLDFB_NO_COL_MAX];
Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX];
Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX];
Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX];
Word32 workBuffer[256];
Word16 num_slots = 1;
FOR (i=0; icldfbAna_Fx,
ppBuf_Real,
ppBuf_Imag,
scale,
timeIn,
0,
CLDFB_NO_COL_MAX,
workBuffer
);
enerScale.lb_scale = negate(scale->lb_scale);
enerScale.lb_scale16 = negate(scale->lb_scale);
/* get 16bit respresentation */
AnalysisPostSpectrumScaling_Fx (
st_fx->cldfbAna_Fx,
ppBuf_Real,
ppBuf_Imag,
ppBuf_Real16,
ppBuf_Imag16,
&enerScale.lb_scale16
);
/* get the energy */
GetEnergyCldfb( &st_fx->energyCoreLookahead_Fx,
&st_fx->sf_energyCoreLookahead_Fx,
num_slots,
ppBuf_Real16,
ppBuf_Imag16,
enerScale.lb_scale16,
st_fx->cldfbAna_Fx->no_channels,
st_fx->cldfbAna_Fx->no_col,
&st_fx->currEnergyHF_fx,
&st_fx->currEnergyHF_e_fx,
enerBuffSum,
enerBuffSum_exp,
&st_fx->tecEnc
);
return;
}
void
GetEnergyCldfb( Word32 *energyLookahead, /*!< o: Q(*sf_energyLookahead) | pointer to the result in the core look-ahead slot */
Word16 *sf_energyLookahead, /*!< o: pointer to the scalefactor of the result in the core look-ahead slot */
const Word16 numLookahead, /*!< i: Q0 the number of look-ahead time-slots */
Word16 **realValues, /*!< i: Q(sf_Values) | the real part of the CLDFB subsamples */
Word16 **imagValues, /*!< i: Q(sf_Values) | the imaginary part of the CLDFB subsamples */
Word16 sf_Values, /*!< i: scalefactor of the CLDFB subcamples - apply as a negated Exponent */
Word16 numberBands, /*!< i: Q0 | number of CLDFB bands */
Word16 numberCols, /*!< i: Q0 | number of CLDFB subsamples */
Word32 *energyHF, /*!< o: Q31 | pointer to HF energy */
Word16 *energyHF_Exp, /*!< o: pointer to exponent of HF energy */
Word32 *energyValuesSum, /*!< o: Q(2*sf_Values-4) | pointer to sum array of energy values, not initialized*/
Word16 *energyValuesSum_Exp,/*!< o: pointer to exponents of energyValuesSum, not initialized */
HANDLE_TEC_ENC_FX hTecEnc
)
{
Word16 j;
Word16 k;
Word16 s;
Word16 sm;
Word32 nrg;
Word16 numberColsL;
Word16 numberBandsM;
Word16 numberBandsM20;
Word32 energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
Word16 energyValuesSumE[CLDFB_NO_CHANNELS_MAX];
Word16 freqTable[2] = {20, 40};
FOR (k=0; k= 0)
{
Word32 *tempEnergyValuesArry[CLDFB_NO_COL_MAX];
Word16 ScaleX2;
assert(numberCols == CLDFB_NO_COL_MAX);
FOR (j=0; jloBuffer,
hTecEnc->hiTempEnv,
ScaleX2
);
}
FOR (j=0; j< numberBands; j++)
{
energyValuesSum[j] = L_deposit_l(0);
energyValuesSumE[j] = 31;
move16();
FOR (k=0; k 0 )
{
*energyValuesSum_Exp = energyValuesSumE[j];
}
}
FOR (j=0; j< numberBands; j++)
{
energyValuesSum[j] = L_shr_r( energyValuesSum[j], sub( *energyValuesSum_Exp, energyValuesSumE[j] ) );
move32();
}
*energyValuesSum_Exp = sub( *energyValuesSum_Exp, shl( sf_Values, 1 ) );
move16();
IF ( sub(numberBands,20) > 0 )
{
numberBandsM = s_min(numberBands, 40);
numberBandsM20 = sub(numberBandsM, 20);
numberColsL = sub(numberCols, numLookahead);
/* sum up CLDFB energy above 8 kHz */
s = BASOP_util_norm_s_bands2shift(i_mult(numberColsL, numberBandsM20));
s = sub(s,4);
nrg = L_deposit_l(0);
FOR (k=0; k < numberColsL; k++)
{
FOR (j=20; j < numberBandsM; j++)
{
nrg = L_add(nrg, L_shr(energyValues[k][j], s));
}
}
s = sub(sub(shl(sf_Values, 1), 1), s);
sm = sub(s_min(s, *sf_energyLookahead), 1);
*energyHF = L_add(L_shr(nrg, limitScale32(sub(s, sm))),
L_shr(*energyLookahead,sub(*sf_energyLookahead, sm)));
move32();
*energyHF_Exp = negate(sm);
move16();
/* process look-ahead region */
s = BASOP_util_norm_s_bands2shift(i_mult(numLookahead, numberBandsM20));
s = sub(s, 2);
nrg = L_deposit_l(0);
FOR (k = numberColsL; k < numberCols; k++)
{
FOR (j=20; j < numberBandsM; j++)
{
nrg = L_add(nrg, L_shr(energyValues[k][j], s));
}
}
s = sub(shl(sf_Values, 1), s);
sm = sub(s_min(s, 44), 1);
BASOP_SATURATE_WARNING_OFF
/* nrg + 6.1e-5f => value 0x40000000, scale 44 */
*energyLookahead = L_add(L_shr(nrg, sub(s, sm)),
L_shr(0x40000000, s_max(-31, s_min(31, sub(44, sm)))));
move32();
BASOP_SATURATE_WARNING_ON
*sf_energyLookahead = sm;
move16();
return;
}
*energyHF = 0x40000000;
move32();
*energyHF_Exp = 17;
move16();
}
Word16
CLDFB_getNumChannels(Word32 sampleRate)
{
Word16 nChannels = 0;
SWITCH (sampleRate)
{
case 48000:
move16();
nChannels = 60;
BREAK;
case 32000:
move16();
nChannels = 40;
BREAK;
case 25600:
move16();
nChannels = 32;
BREAK;
case 16000:
move16();
nChannels = 20;
BREAK;
case 12800:
move16();
nChannels = 16;
BREAK;
case 8000:
move16();
nChannels = 10;
BREAK;
}
return (nChannels);
}
/*-------------------------------------------------------------------*
* cldfb_get_memory_length()
*
* Return length of filter state for recovery
*--------------------------------------------------------------------*/
static Word16
cldfb_get_memory_length (HANDLE_CLDFB_FILTER_BANK hs)
{
IF (sub(hs->type,CLDFB_ANALYSIS)==0)
{
return (i_mult(hs->no_channels,STATE_BUFFER_SIZE));
}
ELSE
{
return (i_mult(hs->no_channels,(9*2)) );
}
}
/*-------------------------------------------------------------------*
* GetEnergyCldfb()
*
* Remove handle
*--------------------------------------------------------------------*/
void
deleteCldfb (HANDLE_CLDFB_FILTER_BANK * h_cldfb) /* i: cldfb handle */
{
IF ( *h_cldfb != NULL )
{
IF ( (*h_cldfb)->FilterStates != NULL )
{
free((*h_cldfb)->FilterStates);
}
free(*h_cldfb);
}
*h_cldfb = NULL;
}
/*-------------------------------------------------------------------*
* cldfb_init_proto_and_twiddles()
*
* Initializes rom pointer
*--------------------------------------------------------------------*/
static void
cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs) /* i: cldfb handle */
{
/*find appropriate set of rotVecs*/
SWITCH(hs->no_channels)
{
case 10:
hs->rRotVctr = rRotVectr_10;
hs->iRotVctr = iRotVectr_10;
hs->synGain = cldfb_synGain[0];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[0];
hs->scale = cldfb_scale_2_5ms[0];
move16();
IF (hs->type == CLDFB_SYNTHESIS )
{
hs->synScalefactor = add(cldfb_synScale[0],hs->filterScale);
move16();
}
ELSE
{
hs->anaScalefactor = add(cldfb_anaScale[0],hs->filterScale);
move16();
}
break;
case 16:
hs->rRotVctr = rRotVectr_16;
hs->iRotVctr = iRotVectr_16;
hs->synGain = cldfb_synGain[1];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[1];
hs->scale = cldfb_scale_2_5ms[1];
move16();
{
hs->anaScalefactor = add(cldfb_anaScale[1],hs->filterScale);
move16();
}
break;
case 20:
hs->rRotVctr = rRotVectr_20;
hs->iRotVctr = iRotVectr_20;
hs->synGain = cldfb_synGain[2];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[2];
hs->scale = cldfb_scale_2_5ms[2];
move16();
IF (hs->type == CLDFB_SYNTHESIS )
{
hs->synScalefactor = add(cldfb_synScale[2],hs->filterScale);
move16();
}
ELSE
{
hs->anaScalefactor = add(cldfb_anaScale[2],hs->filterScale);
move16();
}
break;
case 32:
hs->rRotVctr = rRotVectr_32;
hs->iRotVctr = iRotVectr_32;
hs->synGain = cldfb_synGain[3];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[3];
hs->scale = cldfb_scale_2_5ms[3];
move16();
{
hs->anaScalefactor = add(cldfb_anaScale[3],hs->filterScale);
move16();
}
break;
case 40:
hs->rRotVctr = rRotVectr_40;
hs->iRotVctr = iRotVectr_40;
hs->synGain = cldfb_synGain[4];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[4];
hs->scale = cldfb_scale_2_5ms[4];
move16();
IF (hs->type == CLDFB_SYNTHESIS )
{
hs->synScalefactor = add(cldfb_synScale[4],hs->filterScale);
move16();
}
ELSE
{
hs->anaScalefactor = add(cldfb_anaScale[4],hs->filterScale);
move16();
}
break;
case 60:
hs->rRotVctr = rRotVectr_60;
hs->iRotVctr = iRotVectr_60;
hs->synGain = cldfb_synGain[5];
move16();
hs->p_filter = cldfb_protoFilter_2_5ms[5];
hs->scale = cldfb_scale_2_5ms[5];
move16();
IF (hs->type == CLDFB_SYNTHESIS )
{
hs->synScalefactor = add(cldfb_synScale[5],hs->filterScale);
move16();
}
ELSE
{
hs->anaScalefactor = add(cldfb_anaScale[5],hs->filterScale);
move16();
}
break;
}
}
#define CLDFB_MEM_EXPONENTS (CLDFB_NO_COL_MAX+9)
/*-------------------------------------------------------------------*
* cldfb_save_memory()
*
* Save the memory of filter; to be restored with cldfb_restore_memory()
*--------------------------------------------------------------------*/
void
cldfb_save_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i: cldfb handle */
{
hs->memory_length = cldfb_get_memory_length(hs);
hs->memory = (Word16 *) calloc( hs->memory_length + CLDFB_MEM_EXPONENTS + 1, sizeof (Word16));
/* save the memory */
Copy (hs->FilterStates, hs->memory, hs->memory_length);
Copy (hs->FilterStates_e, hs->memory+hs->memory_length, CLDFB_MEM_EXPONENTS);
hs->memory[hs->memory_length+CLDFB_MEM_EXPONENTS] = hs->FilterStates_eg;
move16();
return;
}
/*-------------------------------------------------------------------*
* cldfb_restore_memory()
*
* Restores the memory of filter; memory to be save by cldfb_save_memory()
*--------------------------------------------------------------------*/
void
cldfb_restore_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i/o: cldfb handle */
{
Word16 size;
size = cldfb_get_memory_length(hs);
/* read the memory */
Copy (hs->memory, hs->FilterStates, hs->memory_length);
Copy (hs->memory+hs->memory_length, hs->FilterStates_e, CLDFB_MEM_EXPONENTS);
hs->FilterStates_eg = hs->memory[hs->memory_length+CLDFB_MEM_EXPONENTS];
move16();
/* adjust sample rate if it was changed in the meanwhile */
IF (sub (hs->memory_length,size) != 0)
{
lerp(hs->FilterStates, hs->FilterStates, size, hs->memory_length);
}
hs->memory_length = 0;
free(hs->memory);
hs->memory = NULL;
return;
}
/*-------------------------------------------------------------------*
* cldfb_reset_memory()
*
* Resets the memory of filter.
*--------------------------------------------------------------------*/
void
cldfb_reset_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i/o: cldfb handle */
{
Word16 length;
length = cldfb_get_memory_length(hs);
/* erase the memory */
set16_fx (hs->FilterStates, 0, length);
set16_fx (hs->FilterStates_e, 0, sizeof(hs->FilterStates_e)/sizeof(hs->FilterStates_e[0]));
hs->FilterStates_eg = 0;
move16();
}