- reference source code for EVS codec

This commit is contained in:
2018-11-30 13:09:22 +02:00
parent 8c16c048dc
commit 94465da48e
422 changed files with 288315 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "options.h"
#include "basop_util.h"
#include "cnst_fx.h"
#include "prot_fx.h"
#include "rom_com_fx.h"
#include "stl.h"
/* Returns: index of next coefficient */
Word16 get_next_coeff_mapped(
Word16 ii[2], /* i/o: coefficient indexes */
Word16 *pp, /* o : peak(1)/hole(0) indicator */
Word16 *idx, /* o : index in unmapped domain */
CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */
)
{
Word16 p;
p = s_and(sub(ii[1], hm_cfg->numPeakIndices), sub(hm_cfg->indexBuffer[ii[1]], hm_cfg->indexBuffer[ii[0]]));
if (p > 0)
{
p = 0;
move16();
}
if (p < 0)
{
p = 1;
move16();
}
*pp = p;
move16();
*idx = ii[p];
move16();
ii[p] = add(ii[p], 1);
move16();
return hm_cfg->indexBuffer[*idx];
}
/* Returns: index of next coefficient */
Word16 get_next_coeff_unmapped(
Word16 ii[2], /* i/o: coefficient indexes */
Word16 *pp, /* o : peak(1)/hole(0) indicator */
Word16 *idx, /* o : index in unmapped domain */
CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */
)
{
(void)pp;
(void)hm_cfg;
*idx = ii[0];
move16();
ii[0] = add(ii[0], 1);
move16();
return *idx;
}
Word16 update_mixed_context(Word16 ctx, Word16 a)
{
Word32 t32;
Word16 t=0; /* initialize just to avoid compiler warning */
t32 = L_mac0(1-13, s_and(a, ~1), add(shr(a, 2), 1));
if (t32 <= 0)
{
t = extract_l(t32);
}
a = shr(a, 3);
if (t32 > 0)
{
t = s_min(a, 2);
}
return add(shl(s_and(ctx, 0xf), 4), add(t, 13));
}
+57
View File
@@ -0,0 +1,57 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include "assert.h"
#include "prot_fx.h"
#include "basop_mpy.h"
#include "cnst_fx.h"
#include "stl.h"
/**
* \brief 31x16 Bit multiply (x*y)
*
* \param[i] xh high part, bit [30..15]
* \param[i] xl low part, 15 LSBits
* \param[i] y
*
* \return x*y
*/
Word32 L_multi31x16_X2(Word16 xh, Word16 xl, Word16 y)
{
Word32 z;
z = L_shl(L_mult0(xh,y),15);
z = L_mac0(z,xl,y);
return z;
}
/*---------------------------------------------------------------
Ari 14 bits common routines
-------------------------------------------------------------*/
/**
* \brief Integer Multiply
*
* \param[i] r
* \param[i] c
*
* \return r*c
*/
Word32 mul_sbc_14bits(Word32 r, Word16 c)
{
Word32 ret;
/*
temp = (((int32) r)*((int32) c))>>stat_bitsnew;
*/
assert(stat_bitsnew == 14);
ret = Mpy_32_16_1(L_shl(r,15-stat_bitsnew), c);
/*assert( (((int) r)*((int) c))>>stat_bitsnew == ret);*/
return (ret);
}
+292
View File
@@ -0,0 +1,292 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "stl.h"
#include "cnst_fx.h"
#include "basop_util.h"
#include "rom_com_fx.h"
#include "prot_fx.h"
void UnmapIndex(
Word16 PeriodicityIndex,
Word16 Bandwidth,
Word16 LtpPitchLag,
Word8 SmallerLags,
Word16 *FractionalResolution,
Word32 *Lag)
{
Word16 LtpPitchIndex, Multiplier;
Word16 Lag16;
test();
IF ((LtpPitchLag > 0) && (s_and(PeriodicityIndex, kLtpHmFlag) != 0))
{
LtpPitchIndex = shr(PeriodicityIndex, 9);
Multiplier = s_and(PeriodicityIndex, 0xff);
assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16);
assert(1 <= Multiplier && Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex]));
*FractionalResolution = kLtpHmFractionalResolution;
move16();
*Lag = L_shr(L_mult0(LtpPitchLag, Ratios[Bandwidth][LtpPitchIndex][Multiplier-1]), 8);
move32();
}
ELSE
{
IF (sub(PeriodicityIndex, 16) < 0)
{
*FractionalResolution = 3;
move16();
Lag16 = add(PeriodicityIndex, GET_ADJ2(0, 6, 3));
}
ELSE IF (sub(PeriodicityIndex, 80) < 0)
{
*FractionalResolution = 4;
move16();
Lag16 = add(PeriodicityIndex, GET_ADJ2(16, 8, 4));
}
ELSE IF (sub(PeriodicityIndex, 208) < 0)
{
*FractionalResolution = 3;
move16();
Lag16 = add(PeriodicityIndex, GET_ADJ2(80, 12, 3));
}
ELSE {
test();
IF (sub(PeriodicityIndex, 224) < 0 || SmallerLags != 0)
{
*FractionalResolution = 1;
move16();
Lag16 = add(PeriodicityIndex, GET_ADJ2(208, 28, 1));
}
ELSE {
*FractionalResolution = 0;
move16();
Lag16 = add(PeriodicityIndex, GET_ADJ2(224, 188, 0));
}
}
*Lag = L_deposit_l(Lag16);
}
}
void ConfigureContextHm(
Word16 NumCoeffs, /* (I) Number of coefficients */
Word16 TargetBits, /* (I) Target bit budget (excl. Done flag) */
Word16 PeriodicityIndex, /* (I) Pitch related index */
Word16 LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */
CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */
)
{
Word8 Bandwidth, SmallerLags;
Word32 i, Limit, Lag;
Word16 j, Index, FractionalResolution;
Word16 *tmp;
Bandwidth = 0;
move16();
if (sub(NumCoeffs, 256) >= 0)
{
Bandwidth = 1;
move16();
}
SmallerLags = 0;
move16();
test();
if ((sub(TargetBits, kSmallerLagsTargetBitsThreshold) <= 0) || (Bandwidth == 0))
{
SmallerLags = 1;
move16();
}
UnmapIndex(PeriodicityIndex,
Bandwidth,
LtpPitchLag,
SmallerLags,
&FractionalResolution, &Lag);
/* Set up and fill peakIndices */
hm_cfg->peakIndices = hm_cfg->indexBuffer;
tmp = hm_cfg->peakIndices;
Limit = L_shl(L_deposit_l(sub(NumCoeffs, 1)), FractionalResolution);
IF (L_sub(Lag, Limit) < 0)
{
FOR (i=Lag; i<Limit; i+=Lag)
{
Index = extract_l(L_shr(i, FractionalResolution));
*tmp++ = sub(Index, 1);
move16();
*tmp++ = Index;
move16();
*tmp++ = add(Index, 1);
move16();
}
}
hm_cfg->numPeakIndices = (Word16)(tmp - hm_cfg->indexBuffer);
/* Set up and fill holeIndices */
hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices;
tmp = hm_cfg->holeIndices;
Index = 0;
move16();
IF (hm_cfg->numPeakIndices > 0)
{
FOR (j=0; j<hm_cfg->numPeakIndices; j+=3)
{
FOR (; Index<hm_cfg->peakIndices[j]; ++Index)
{
*tmp++ = Index;
move16();
}
Index = add(Index, 3); /* Skip the peak */
}
}
IF (sub(Index, NumCoeffs) < 0)
{
FOR (; Index<NumCoeffs; ++Index)
{
*tmp++ = Index;
move16();
}
}
hm_cfg->numHoleIndices = (Word16)(tmp - hm_cfg->holeIndices);
*tmp++ = NumCoeffs;
move16(); /* Add extremal element signaling the end of the buffer */
}
Word16 CountIndexBits(
Word16 Bandwidth,
Word16 PeriodicityIndex)
{
Word16 result;
Word16 PeriodicityIndexS;
result = 8;
move16();
PeriodicityIndexS = shr(PeriodicityIndex, 9);
if (s_and(PeriodicityIndex, kLtpHmFlag) != 0)
{
result = NumRatioBits[Bandwidth][PeriodicityIndexS];
move16();
}
return result;
}
int tcx_hm_render(
Word32 lag, /* i: pitch lag Q0 */
Word16 fract_res, /* i: fractional resolution of the lag Q0 */
Word16 p[] /* o: harmonic model Q13 */
)
{
Word16 k, tmp, height;
Word16 PeakDeviation;
Word32 f0, tmp32;
/* Set up overall shape */
f0 = L_shl(lag, sub(15, fract_res)); /* Q31 */
tmp32 = Mpy_32_16_1(f0, -26474);
tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2);
tmp32 = L_sub(603979776L, tmp32);
tmp32 = L_add(L_add(tmp32, tmp32), Mpy_32_16_1(tmp32, 26214));
height = round_fx(tmp32); /* Q13 */
tmp32 = Mpy_32_16_1(f0, -18910);
tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2);
tmp32 = L_sub(1395864371L, tmp32);
PeakDeviation = round_fx(tmp32); /* Q14 */
IF( sub(13915,PeakDeviation) > 0 )
{
/* A bit error was encountered */
return 1;
}
ELSE
{
tmp = div_s(13915, PeakDeviation);
tmp = mult_r(tmp, tmp); /* Q15 */
}
tmp = div_s(13915, PeakDeviation);
tmp = mult_r(tmp, tmp); /* Q15 */
/* Render the prototype peak */
p[kTcxHmParabolaHalfWidth] = height;
move16();
FOR (k=1; k<=kTcxHmParabolaHalfWidth; ++k)
{
p[kTcxHmParabolaHalfWidth+k] = round_fx(Mpy_32_16_1(BASOP_Util_InvLog2(L_shl(L_mult0(i_mult2(negate(k),k), tmp),10)), height));
}
/* Mirror */
FOR (k=-kTcxHmParabolaHalfWidth; k<0; ++k)
{
p[kTcxHmParabolaHalfWidth+k] = p[kTcxHmParabolaHalfWidth-k];
move16();
}
return 0;
}
void tcx_hm_modify_envelope(
Word16 gain, /* i: HM gain Q11 */
Word32 lag, /* i: pitch lag Q0 */
Word16 fract_res, /* i: fractional resolution of the lag Q0 */
Word16 p[], /* i: harmonic model Q13 */
Word32 env[], /* i/o: envelope Q16 */
Word16 L_frame /* i: number of spectral lines Q0 */
)
{
Word16 k, h, x, l1,l2, L_frame_m1, L_frame_for_loop;
Word16 inv_shape[2*kTcxHmParabolaHalfWidth+1];
IF ( gain == 0 )
{
return;
}
FOR (k=0; k<2*kTcxHmParabolaHalfWidth+1; ++k)
{
/* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */
inv_shape[k] = div_s(512, add(512, mult_r(gain, p[k])));
move16();
}
h = 1;
move16();
k = extract_l(L_shr(lag,fract_res));
L_frame_m1 = sub(L_frame,1);
L_frame_for_loop = add(L_frame,kTcxHmParabolaHalfWidth - 1);
WHILE ( sub(k,L_frame_for_loop) <= 0 )
{
l1 = s_max(0, sub(k,kTcxHmParabolaHalfWidth));
l2 = s_min(add(k,kTcxHmParabolaHalfWidth), L_frame_m1);
FOR (x=l1; x<=l2; ++x)
{
env[x] = Mpy_32_16_1(env[x], inv_shape[x-k+kTcxHmParabolaHalfWidth]);
move32();
}
h = add(h,1);
k = extract_l(L_shr(imult3216(lag,h),fract_res));
}
}
+471
View File
@@ -0,0 +1,471 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "prot_fx.h"
#include "basop_util.h"
#include "options.h"
#include "cnst_fx.h"
#include "stl.h"
/* Fixed point implementation of exp(negate()) */
Word32 expfp( /* o: Q31 */
Word16 x, /* i: mantissa Q-e */
Word16 x_e) /* i: exponent Q0 */
{
Word16 xi, xf, tmp;
Word16 b0, b1, b2, b3;
Word32 y, L_tmp;
assert(x > 0);
L_tmp = L_shl(L_deposit_h(x), x_e);
/* split into integer and fractional parts */
xi = round_fx(L_tmp);
xf = extract_l(L_tmp);
BASOP_SATURATE_WARNING_OFF;
xf = negate(xf);
BASOP_SATURATE_WARNING_ON;
/* Fractional part */
/* y = 65536
+ xf
+ ((xf*xf) / (2*65536))
+ ((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)
+ ((((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)*xf) / (4*65536)); */
y = L_mac0(65536, xf, 1);
tmp = shr(mult(xf, xf), 2);
y = L_mac0(y, tmp, 1);
tmp = shr(mult(shr(mult(tmp, xf), 1), 65536/3), 1);
y = L_mac0(y, tmp, 1);
tmp = shr(mult(tmp, xf), 3);
y = L_mac0(y, tmp, 1);
/* Integer part */
b0 = s_and(xi, 1);
b1 = s_and(xi, 2);
b2 = s_and(xi, 4);
b3 = s_and(xi, 8);
if (b0 != 0) y = Mpy_32_16_1(y, 24109); /* exp(-1) in -1Q16 */
if (b1 != 0) y = Mpy_32_16_1(y, 17739); /* exp(-2) in -2Q17 */
if (b2 != 0) y = Mpy_32_16_1(y, 19205); /* exp(-4) in -5Q20 */
if (b3 != 0) y = Mpy_32_16_1(y, 22513); /* exp(-8) in -11Q26 */
/* scaling: -1*b0 - 2*b1 -5*b2 -11*b3 */
y = L_shr(y, add(add(xi, shr(xi, 2)), shr(b3, 3)));
/* zero for xi >= 16 */
if (shr(xi, 4) > 0)
{
y = L_deposit_l(0);
}
return L_shl(y, 15);
}
/* Fixed point implementation of pow(), where base is fixed point (16/16) and exponent a small *odd* integer
*
* Returns: *pout1 = ( (base/65536)^(2*exp - 1) ) * 65536
* *pout2 = ( (base/65536)^(2*exp + 1) ) * 65536
*
* NOTE: This function must be in sync with ari_decode_14bits_pow() */
void powfp_odd2(Word16 base, /* Q15 */
Word16 exp, /* Q0 */
Word16 *pout1, /* Q15 */
Word16 *pout2) /* Q15 */
{
/* this version is in sync with ari_enc_14bits_pow()
* that is, we have to start multiplication from the largest power-of-two, in order to
* get the rounding errors to appear at the same places */
Word16 pows[12]; /* powers of two exponents*/
Word16 exp2;
Word16 out, out2;
Word16 k, h, maxk;
assert(exp >= 0);
out = base;
move16();
out2 = 0x7FFF;
move16();
IF (exp != 0)
{
exp2 = sub(exp, 1);
maxk = sub(15, norm_s(exp));
assert(maxk < 12);
pows[0] = base;
move16();
FOR (k = 0; k < maxk; k++)
{
pows[k+1] = mult_r(pows[k], pows[k]);
move16();
}
k = sub(k, 1);
h = shl(1, k); /* highest bit of exp2 */
out2 = base;
move16();
out = mult_r(out, pows[k+1]); /* we already know that "exp" has the highest bit set to one since we calculated .. */
/* .. the effective length of "exp" earlier on, thus we omit the branch for out2 */
if (s_and(exp2, h) != 0)
{
out2 = mult_r(out2, pows[k+1]);
}
h = shr(h, 1);
FOR (k = sub(k, 1); k >= 0; k--)
{
if (s_and(exp, h) != 0)
{
out = mult_r(out, pows[k+1]);
}
if (s_and(exp2, h) != 0)
{
out2 = mult_r(out2, pows[k+1]);
}
h = shr(h, 1);
}
}
*pout1 = out2;
move16();
*pout2 = out;
move16();
}
/*------------------------------------------------------------------------
* Function: tcx_arith_scale_envelope
*
* For optimal performance of the arithmetic coder, the envelope shape must
* be scaled such that the expected bit-consumption of a signal that
* follows the scaled shape coincides with the target bitrate.
* This function calculates a first-guess scaling and then uses the bi-section
* search to find the optimal scaling.
*
* We assume that lines follow the Laplacian distribution, whereby the expected
* bit-consumption would be log2(2*e*s[k]), where s[k] is the envelope value
* for the line in question. However, this theoretical formula assumes that
* all lines are encoded with magnitude+sign. Since the sign is unnecessary
* for 0-values, that estimate of bit-consumption is biased when s[k] is small.
* Analytical solution of the expectation for small s[k] is difficult, whereby
* we use the approximation log2(2*e*s[k] + 0.15 + 0.035 / s[k]) which is accurate
* on the range 0.08 to 1.0.
*
* NOTE: This function must be bit-exact on all platforms such that encoder
* and decoder remain synchronized.
*-------------------------------------------------------------------------*/
void tcx_arith_scale_envelope(
Word16 L_spec_core, /* i: number of lines to scale Q0 */
Word16 L_frame, /* i: number of lines Q0 */
Word32 env[], /* i: unscaled envelope Q16 */
Word16 target_bits, /* i: number of available bits Q0 */
Word16 low_complexity, /* i: low-complexity flag Q0 */
Word16 s_env[], /* o: scaled envelope Q15-e */
Word16 *s_env_e /* o: scaled envelope exponent Q0 */
)
{
Word32 ienv[N_MAX_ARI];
Word16 scale, iscale, iscale_e, a_e, b, b_e;
Word16 lob, hib, adjust;
Word16 k, iter, max_iter, lob_bits, hib_bits;
Word16 statesi, bits;
Word32 mean, a, s, L_tmp;
Word16 mean_e, tmp, tmp2;
lob_bits = 0;
move16();
hib_bits = 0;
move16();
/* Boosting to account for expected spectrum truncation (kMax) */
/* target_bits = (int)(target_bits * (1.2f - 0.00045f * target_bits + 0.00000025f * target_bits * target_bits)); */
L_tmp = L_shr(Mpy_32_16_1(L_mult0(target_bits, target_bits), 17180), 6); /* Q15; 17180 -> 0.00000025f (Q36) */
L_tmp = L_sub(L_tmp, L_shr(L_mult0(target_bits, 30199), 11)); /* Q15; 30199 -> 0.00045f (Q26) */
L_tmp = L_add(L_tmp, 39322); /* Q15; 39322 -> 1.2f (Q15) */
L_tmp = Mpy_32_16_1(L_tmp, target_bits); /* Q0 */
assert(L_tmp < 32768);
target_bits = extract_l(L_tmp);
/* Calculate inverse envelope and find initial scale guess based on mean */
mean = L_deposit_l(0);
FOR (k = 0; k < L_frame; k++)
{
/* ienv[k] = 1.0f / env[k];
mean += ienv[k]; */
tmp = norm_l(env[k]);
tmp2 = sub(15, tmp);
tmp = Inv16(round_fx(L_shl(env[k], tmp)), &tmp2);
ienv[k] = L_shl(L_deposit_h(tmp), sub(tmp2, 15)); /* Q16 */ move32();
mean = L_add(mean, ienv[k]);
}
tmp = norm_s(L_frame);
tmp = shl(div_s(8192, shl(L_frame, tmp)), sub(tmp, 7));
mean = L_shr(Mpy_32_16_1(mean, tmp), 6); /* Q16 */
/* Rate dependent compensation to get closer to the target on average */
/* mean = (float)pow(mean, (float)L_frame / (float)target_bits * 0.357f); */
tmp = BASOP_Util_Divide1616_Scale(L_frame, target_bits, &tmp2);
tmp = mult_r(tmp, 11698/*0.357f Q15*/);
mean = BASOP_Util_fPow(mean, 15, L_deposit_h(tmp), tmp2, &mean_e);
/* Find first-guess scaling coefficient "scale" such that if "mean" is the
* mean of the envelope, then the mean bit-consumption is approximately
*
* log2(2*e*mean*scale + 0.15 + 0.035/(mean*scale)) * L_frame = target_bits
*/
/* a = 2*2.71828183f*mean*mean; */
tmp = round_fx(mean);
a = L_mult(mult_r(tmp, 22268/*2.71828183f Q13*/), tmp);
a_e = add(shl(mean_e, 1), 3);
/* b = (0.15f - (float)pow(2.0f, target_bits/(float)L_frame)) * mean; */
tmp = BASOP_Util_Divide1616_Scale(target_bits, L_frame, &tmp2);
tmp = round_fx(BASOP_util_Pow2(L_deposit_h(tmp), tmp2, &tmp2));
b_e = BASOP_Util_Add_MantExp(4915/*0.15f Q15*/, 0, negate(tmp), tmp2, &b);
b = mult_r(b, round_fx(mean));
b_e = add(b_e, mean_e);
/* scale = (-b + (float)sqrt(b*b - 4.0f*a*0.035f)) / (2.0f * a); */
tmp = round_fx(BASOP_Util_Add_Mant32Exp(L_mult(b, b), shl(b_e, 1), Mpy_32_16_1(a, -4588/*-4.0f*0.035f Q15*/), a_e, &tmp2));
IF( tmp <= 0 )
{
tmp = 0;
set16_fx(s_env, 0, L_frame);
}
ELSE
{
tmp = Sqrt16(tmp, &tmp2);
}
tmp2 = BASOP_Util_Add_MantExp(negate(b), b_e, tmp, tmp2, &scale);
scale = BASOP_Util_Divide1616_Scale(scale, round_fx(a), &tmp);
scale = shl(scale, sub(sub(add(tmp, tmp2), a_e), 1)); /* Q15 */
/* iscale = 1.0f / scale; */
iscale_e = 0;
move16();
iscale = Inv16(s_max(1, scale), &iscale_e);
lob = 0;
move16();
hib = 0;
move16();
max_iter = 2;
move16();
if(low_complexity)
{
max_iter = 1;
move16();
}
FOR (iter = 0; iter < max_iter; iter++)
{
statesi = 0x7FFF;
move16();
bits = 0;
move16();
FOR (k = 0; k < L_frame; k++)
{
s = Mpy_32_16_1(ienv[k], scale); /* Q16 */
IF (L_sub(s, 5243l/*0.08f Q16*/) <= 0)
{
/* If s = 0.08, the expected bit-consumption is log2(1.0224). Below 0.08, the bit-consumption
estimate function becomes inaccurate, so use log2(1.0224) for all values below 0.08. */
/* round(state * 1.0224 * 32768) */
statesi = mult_r(statesi, 16751/*1.0224 Q14*/);
tmp = norm_s(statesi);
statesi = shl(statesi, tmp);
bits = add(bits, sub(1, tmp));
}
ELSE IF (L_sub(s, 16711680l/*255.0 Q16*/) <= 0)
{
/* a = 5.436564f * s + 0.15f + 0.035f * env[k] * iscale; */
L_tmp = L_shl(Mpy_32_16_1(s, 22268/*5.436564f Q12*/), 3);
L_tmp = L_add(L_tmp, 9830l/*0.15f Q16*/);
L_tmp = L_add(L_tmp, L_shl(Mpy_32_16_1(env[k], mult_r(1147/*0.035f Q15*/, iscale)), iscale_e));
tmp = norm_l(L_tmp);
statesi = mult_r(statesi, round_fx(L_shl(L_tmp, tmp)));
bits = add(bits, sub(15, tmp));
tmp = norm_s(statesi);
statesi = shl(statesi, tmp);
bits = sub(bits, tmp);
}
ELSE
{
/* for large envelope values, s > 255, bit consumption is approx log2(2*e*s)
* further, we use round(log2(x)) = floor(log2(x)+0.5) = floor(log2(x*sqrt(2))) */
/* a = 5.436564f * s; */
L_tmp = Mpy_32_16_1(s, 31492/*5.436564f * 1.4142f Q12*/); /* Q13 */
bits = add(bits, sub(17, norm_l(L_tmp)));
}
}
IF (sub(bits, target_bits) <= 0) /* Bits leftover => scale is too small */
{
lob = scale;
move16();
lob_bits = bits;
move16();
IF (hib > 0) /* Bisection search */
{
adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits));
scale = add(mult_r(sub(lob, hib), adjust), hib);
}
ELSE /* Initial scale adaptation */
{
/* adjust = 1.05f * target_bits / (float)bits;
scale *= adjust; */
adjust = mult_r(17203/*1.05f Q14*/, target_bits);
adjust = BASOP_Util_Divide1616_Scale(adjust, bits, &tmp);
scale = shl(mult_r(scale, adjust), add(1, tmp));
}
}
ELSE /* Ran out of bits => scale is too large */
{
hib = scale;
move16();
hib_bits = bits;
move16();
IF (lob > 0) /* Bisection search */
{
adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits));
scale = add(mult_r(sub(lob, hib), adjust), hib);
}
ELSE { /* Initial scale adaptation */
test();
IF( target_bits <= 0 || bits <= 0 ) /* safety check in case of bit errors */
{
adjust = 0;
move16();
set16_fx( s_env, 0, L_frame );
}
ELSE
{
adjust = div_s(mult_r(31130/*0.95f Q15*/, target_bits), bits);
}
scale = mult_r(scale, adjust);
}
}
iscale_e = 0;
move16();
IF( scale == 0 ) /* safety check in case of bit errors */
{
iscale = 0;
move16();
set16_fx( s_env, 0, L_frame );
}
ELSE
{
iscale = Inv16(scale, &iscale_e);
}
}
L_frame = L_spec_core;
move16();
tmp = getScaleFactor32(env, L_frame);
*s_env_e = sub(add(15, iscale_e), tmp);
move16();
BASOP_SATURATE_WARNING_OFF;
a = L_shl(1265000, sub(15, *s_env_e));
BASOP_SATURATE_WARNING_ON;
FOR (k = 0; k < L_frame; k++)
{
L_tmp = Mpy_32_16_1(L_shl(env[k], tmp), iscale);
L_tmp = L_min(L_tmp, a);
s_env[k] = round_fx(L_tmp);
}
}
/*------------------------------------------------------------------------
* Function: tcx_arith_render_envelope
*
* Calculate the envelope of the spectrum based on the LPC shape. The
* envelope is used in a perceptual domain, whereby the LPC shape has to
* be multiplied by the perceptual model.
* Operations that are performed on the spectrum, which change the magnitude
* expectation of lines, such as low-frequency emphasis, are included in the
* envelope shape.
* NOTE: This function must be bit-exact on all platforms such that encoder
* and decoder remain synchronized.
*-------------------------------------------------------------------------*/
void tcx_arith_render_envelope(
const Word16 A_ind[], /* i: LPC coefficients of signal envelope */
Word16 L_frame, /* i: number of spectral lines */
Word16 L_spec,
Word16 preemph_fac, /* i: pre-emphasis factor */
Word16 gamma_w, /* i: A_ind -> weighted envelope factor */
Word16 gamma_uw, /* i: A_ind -> non-weighted envelope factor */
Word32 env[] /* o: shaped signal envelope */
)
{
Word16 k;
Word16 tmpA[M+2];
Word16 signal_env[FDNS_NPTS], signal_env_e[FDNS_NPTS];
Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS];
/* Compute perceptual LPC envelope, transform it into freq.-domain gains */
weight_a_fx( A_ind, tmpA, gamma_w, M );
lpc2mdct( tmpA, M, NULL, NULL, gainlpc, gainlpc_e );
/* Add pre-emphasis tilt to LPC envelope, transform LPC into MDCT gains */
E_LPC_a_weight_inv(A_ind, signal_env, gamma_uw, M);
E_LPC_a_add_tilt(signal_env, tmpA, preemph_fac, M);
lpc2mdct(tmpA, M+1, signal_env, signal_env_e, NULL, NULL);
/* Compute weighted signal envelope in perceptual domain */
FOR (k = 0; k < FDNS_NPTS; k++)
{
signal_env[k] = mult_r(signal_env[k], gainlpc[k]);
move16();
signal_env_e[k] = add(signal_env_e[k], gainlpc_e[k]);
move16();
}
/* Adaptive low frequency emphasis */
set32_fx(env, 0x10000, L_frame);
AdaptLowFreqDeemph(env, 15,
1,
gainlpc, gainlpc_e,
L_frame, NULL);
/* Scale from FDNS_NPTS to L_frame and multiply LFE gains */
mdct_noiseShaping_interp(env, L_frame, signal_env, signal_env_e);
FOR (k=L_frame; k<L_spec; ++k)
{
env[k] = env[k-1];
move32();
}
}
+58
View File
@@ -0,0 +1,58 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "basop_mpy.h"
#include "stl.h"
#include "options.h" /* Needed for Stack Counting Mechanism Macros (when Instrumented) */
Word32 Mpy_32_16_1(Word32 x, Word16 y)
{
Word32 mh;
UWord16 ml;
Mpy_32_16_ss(x, y, &mh, &ml);
return (mh);
}
Word32 Mpy_32_16_r(Word32 x, Word16 y)
{
Word32 mh;
UWord16 ml;
Mpy_32_16_ss(x, y, &mh, &ml);
if(s_and(ml, -32768 /* 0x8000 */))
{
mh = L_add(mh, 1);
}
return (mh);
}
Word32 Mpy_32_32(Word32 x, Word32 y)
{
Word32 mh;
UWord32 ml;
Mpy_32_32_ss(x, y, &mh, &ml);
return (mh);
}
Word32 Mpy_32_32_r(Word32 x, Word32 y)
{
Word32 mh;
UWord32 ml;
Mpy_32_32_ss(x, y, &mh, &ml);
if(L_and(ml, 0x80000000))
{
mh = L_add(mh, 1);
}
return (mh);
}
+104
View File
@@ -0,0 +1,104 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef __BASOP_MPY_H
#define __BASOP_MPY_H
#include "stl.h"
#include "options.h"
/**
* \brief 32*16 Bit fractional Multiplication using 40 bit OPS
* Performs a multiplication of a 32-bit variable x by
* a 16-bit variable y, returning a 32-bit value.
*
* \param[i] x
* \param[i] y
*
* \return x*y
*/
Word32 Mpy_32_16_1(Word32 x,
Word16 y);
/**
* \brief 32*16 Bit fractional Multiplication using 40 bit OPS
* Performs a multiplication of a 32-bit variable x by
* a 16-bit variable y incl. rounding, returning a 32-bit value.
*
* \param[i] x
* \param[i] y
*
* \return x*y
*/
Word32 Mpy_32_16_r(Word32 x,
Word16 y);
/**
* \brief 32*32 Bit fractional Multiplication using 40 bit OPS
*
* Performs a multiplication of a 32-bit variable x by
* a 32-bit variable y, returning a 32-bit value.
*
* \param[i] x
* \param[i] y
*
* \return x*y
*/
Word32 Mpy_32_32(Word32 x,
Word32 y);
/**
* \brief 32*32 Bit fractional Multiplication using 40 bit OPS including rounding
*
* Performs a multiplication of a 32-bit variable x by
* a 32-bit variable y, returning a 32-bit value.
*
* \param[i] x
* \param[i] y
*
* \return x*y
*/
Word32 Mpy_32_32_r(Word32 x, Word32 y);
/**
* \brief 32*16 Bit integer Multiplication using 40 bit OPS
*
* Performs a multiplication of a 32-bit variable x by
* a 16-bit variable y, returning a 32-bit value.
*
* \param[i] x
* \param[i] y
*
* \return x*y
*/
Word32 Mpy_32_16_2(Word32 x,
Word16 y);
/**
* \brief 32*16 Bit complex fractional multiplication using 40 Bit and 32 Bit operators
*
* The function mixes 40 Bit and 32 Bit operators, thus it must not be applied
* inside of loops where 32 and 16 bit operators are used.
*
* \param[i] c_Re
* \param[i] c_Im
* \param[i] a_Re
* \param[i] a_Im
* \param[i] b_Re
* \param[i] b_Im
*
* \return none
*/
void cplxMpy_32_16(Word32 *c_Re,
Word32 *c_Im,
const Word32 a_Re,
const Word32 a_Im,
const Word16 b_Re,
const Word16 b_Im
);
#define MUL_F(A,B) Mpy_32_16_1((A),(B))
#endif /* __BASOP_SETTINGS_H */
File diff suppressed because it is too large Load Diff
+817
View File
@@ -0,0 +1,817 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef __BASOP_UTIL_H__
#define __BASOP_UTIL_H__
#include "stl.h"
#include "typedef.h"
#include "basop32.h"
#include "basop_mpy.h"
#define _LONG long
#define _SHORT short
#ifdef _WIN32
#define _INT64 __int64
#else
#define _INT64 long long
#endif
#define WORD32_BITS 32
#define MAXVAL_WORD32 ((signed)0x7FFFFFFF)
#define MINVAL_WORD32 ((signed)0x80000000)
#define WORD32_FIX_SCALE ((_INT64)(1)<<(WORD32_BITS-1))
#define WORD16_BITS 16
#define MAXVAL_WORD16 (((signed)0x7FFFFFFF)>>16)
#define MINVAL_WORD16 (((signed)0x80000000)>>16)
#define WORD16_FIX_SCALE ((_INT64)(1)<<(WORD16_BITS-1))
/*!
\def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation
*/
#define WORD322WORD16(val) \
( ( ((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) > (((_LONG)1<<WORD16_BITS)-1)) && ((_LONG)(val) > 0) ) ? \
(Word16)(_SHORT)(((_LONG)1<<(WORD16_BITS-1))-1):(Word16)(_SHORT)((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) >> 1) )
/* Word16 Packed Type */
typedef struct
{
struct
{
Word16 re;
Word16 im;
} v;
} PWord16;
#define cast16 move16
#define LD_DATA_SCALE (6)
#define LD_DATA_SHIFT_I5 (7)
#define modDiv2(x) sub(x,shl(shr(x,1),1))
#define modDiv8(x) L_sub(x,L_shl(L_shr(x,3),3))
static __inline Word16 limitScale16( Word16 s)
{
/* It is assumed, that s is calculated just before, therefore we can switch upon sign */
if (s >= 0)
s = s_min(s,WORD16_BITS-1);
if (s < 0)
s = s_max(s,1-WORD16_BITS);
return (s);
}
static __inline Word16 limitScale32( Word16 s)
{
/* It is assumed, that s is calculated just before, therefore we can switch upon sign */
if (s >= 0)
s = s_min(s, WORD32_BITS-1);
if (s < 0)
s = s_max(s, 1-WORD32_BITS);
return (s);
}
/*!**********************************************************************
\brief Add two values given by mantissa and exponent.
Mantissas are in 16-bit-fractional format with values between 0 and 1. <br>
The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
************************************************************************/
Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */
(Word16 a_m, /*!< Mantissa of 1st operand a */
Word16 a_e, /*!< Exponent of 1st operand a */
Word16 b_m, /*!< Mantissa of 2nd operand b */
Word16 b_e, /*!< Exponent of 2nd operand b */
Word16 *ptrSum_m); /*!< Mantissa of result */
/************************************************************************/
/*!
\brief Divide two values given by mantissa and exponent.
Mantissas are in 16-bit-fractional format with values between 0 and 1. <br>
The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
For performance reasons, the division is based on a table lookup
which limits accuracy.
*/
void BASOP_Util_Divide_MantExp (Word16 a_m, /*!< Mantissa of dividend a */
Word16 a_e, /*!< Exponent of dividend a */
Word16 b_m, /*!< Mantissa of divisor b */
Word16 b_e, /*!< Exponent of divisor b */
Word16 *ptrResult_m, /*!< Mantissa of quotient a/b */
Word16 *ptrResult_e /*!< Exponent of quotient a/b */
);
/************************************************************************/
/*!
\brief Calculate the squareroot of a number given by mantissa and exponent
Mantissa is in 16/32-bit-fractional format with values between 0 and 1. <br>
For *norm versions mantissa has to be between 0.5 and 1. <br>
The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
The exponent is addressed via pointers and will be overwritten with the result.
*/
Word16 Sqrt16( /*!< output mantissa */
Word16 mantissa, /*!< input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
Word16 Sqrt16norm( /*!< output mantissa */
Word16 mantissa, /*!< normalized input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
Word32 Sqrt32( /*!< output mantissa */
Word32 mantissa, /*!< input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
Word32 Sqrt32norm( /*!< output mantissa */
Word32 mantissa, /*!< normalized input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
/* deprecated, use Sqrt16! */
void BASOP_Util_Sqrt_MantExp (Word16 *mantissa, /*!< Pointer to mantissa */
Word16 *exponent /*!< Pointer to exponent */
);
/* deprecated, use Sqrt16norm! */
void BASOP_Util_Sqrt_MantExpNorm (Word16 *mantissa, /*!< Pointer to normalized mantissa */
Word16 *exponent /*!< Pointer to exponent */
);
/****************************************************************************/
/*!
\brief Calculate the inverse of the squareroot of a number given by mantissa and exponent
Mantissa is in 16/32-bit-fractional format with values between 0 and 1. <br>
For *norm versions mantissa has to be between 0.5 and 1. <br>
The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
The exponent is addressed via pointers and will be overwritten with the result.
*/
Word16 ISqrt16( /*!< output mantissa */
Word16 mantissa, /*!< input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
Word32 ISqrt32( /*!< output mantissa */
Word32 mantissa, /*!< input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
Word32 ISqrt32norm( /*!< output mantissa */
Word32 mantissa, /*!< normalized input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
/* deprecated, use ISqrt16! */
void BASOP_Util_InvSqrt_MantExp (Word16 *mantissa, /*!< Pointer to mantissa */
Word16 *exponent /*!< Pointer to exponent */
);
/*****************************************************************************/
/*!
\brief Calculate the inverse of a number given by mantissa and exponent
Mantissa is in 16-bit-fractional format with values between 0 and 1. <br>
The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
The operand is addressed via pointers and will be overwritten with the result.
The function uses a table lookup and a newton iteration.
*/
Word16 Inv16( /*!< output mantissa */
Word16 mantissa, /*!< input mantissa */
Word16 *exponent /*!< pointer to exponent */
);
/******************************************************************************/
/*!
\brief Calculate the squareroot and inverse of squareroot of a number given by mantissa and exponent
Mantissa is in 16-bit-fractional format with values between 0 and 1. <br>
The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
*/
void BASOP_Util_Sqrt_InvSqrt_MantExp (Word16 mantissa, /*!< mantissa */
Word16 exponent, /*!< expoinent */
Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */
Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */
Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */
Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */
);
/********************************************************************/
/*!
\brief Calculates the scalefactor needed to normalize input array
The scalefactor needed to normalize the Word16 input array is returned <br>
If the input array contains only '0', a scalefactor 0 is returned <br>
Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x <br>
and -32768 <= x <= -16384 for negative x
*/
Word16 getScaleFactor16( /* o: measured headroom in range [0..15], 0 if all x[i] == 0 */
const Word16 *x, /* i: array containing 16-bit data */
const Word16 len_x); /* i: length of the array to scan */
/********************************************************************/
/*!
\brief Calculates the scalefactor needed to normalize input array
The scalefactor needed to normalize the Word32 input array is returned <br>
If the input array contains only '0', a scalefactor 0 is returned <br>
Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x <br>
and -2147483648 <= x <= -1073741824 for negative x
*/
Word16 getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */
const Word32 *x, /* i: array containing 32-bit data */
const Word16 len_x); /* i: length of the array to scan */
/**
* \brief normalize mantissa and update the exponent accordingly.
* \param mantissa the mantissa to be normalized
* \param pexponent pointer to the exponent.
* \return the normalized mantissa.
*/
Word16 normalize16(Word16 mantissa, Word16 *pexponent);
/****************************************************************************/
/*!
\brief Does fractional integer division of Word32 arg1 by Word16 arg2
both input arguments may be positive or negative <br>
the result is truncated to Word16
\return fractional integer Word16 result of arg1/arg2
*/
Word16 divide3216( Word32 x, /*!< Numerator*/
Word16 y); /*!< Denominator*/
/****************************************************************************/
/*!
\brief Does fractional integer division of Word16 arg1 by Word16 arg2
both input arguments may be positive or negative <br>
the result is truncated to Word16
\return fractional integer Word16 result of arg1/arg2
*/
Word16 divide1616( Word16 x, /*!< Numerator*/
Word16 y); /*!< Denominator*/
/****************************************************************************/
/*!
\brief Does fractional integer division of Word32 arg1 by Word32 arg2
this function makes both the numerator and the denominator positive integers,
and scales up both values to avoid losing the accuracy of the outcome
too much
WARNING: it should be arg1 < arg2 because of the maximum degree of scaling for the mantissa!
\return fractional Word16 integer z = arg1(32bits)/arg2(32bits)
*/
Word16 divide3232( Word32 x, /*!< Numerator*/
Word32 y); /*!< Denominator*/
/****************************************************************************/
/*!
\brief Does fractional integer division of UWord32 arg1 by UWord32 arg2
This function ensures both the numerator and the denominator are positive integers,
and scales up both values to avoid losing the accuracy of the outcome
too much.<br>
CAUTION: Arg 3 is a Word16 pointer which will point to the scalefactor difference
s_diff = sub(s2,s1), where s1 and s2 are the scalefactors of the arguments, which
were shifted in order to e.g. preserve accuracy.
I.e. the result has to be scaled due to shifting it
s_diff to the right to obtain the real result of the division.
\return fractional Word16 integer z = arg1(32bits)/arg2(32bits)
*/
Word16 BASOP_Util_Divide3232_uu_1616_Scale( Word32 x, /*!< i : Numerator*/
Word32 y, /*!< i : Denominator*/
Word16 *s); /*!< o : Additional scalefactor difference*/
/****************************************************************************/
/*!
\brief Does fractional integer division of Word32 arg1 by Word32 arg2
This function scales up both values to avoid losing the accuracy of the outcome
too much.<br>
CAUTION: Arg 3 is a Word16 pointer which will point to the scalefactor difference
s_diff = sub(s2,s1), where s1 and s2 are the scalefactors of the arguments, which
were shifted in order to e.g. preserve accuracy.
I.e. the result has to be scaled due to shifting it
s_diff to the right to obtain the real result of the division.
\return fractional Word16 integer z = arg1(32bits)/arg2(32bits)
*/
Word16 BASOP_Util_Divide3232_Scale( Word32 x, /*!< i : Numerator*/
Word32 y, /*!< i : Denominator*/
Word16 *s); /*!< o : Additional scalefactor difference*/
/****************************************************************************/
/*!
\brief Does fractional integer division of Word32 arg1 by Word16 arg2
\return fractional Word16 integer z = arg1(32bits)/arg2(16bits) , z not normalized
*/
Word16 BASOP_Util_Divide3216_Scale( Word32 x, /*!< i : Numerator */
Word16 y, /*!< i : Denominator*/
Word16 *s); /*!< o : Additional scalefactor difference*/
/****************************************************************************/
/*!
\brief Does fractional division of Word16 arg1 by Word16 arg2
\return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s
*/
Word16 BASOP_Util_Divide1616_Scale( Word16 x, /*!< i : Numerator*/
Word16 y, /*!< i : Denominator*/
Word16 *s); /*!< o : Additional scalefactor difference*/
/************************************************************************/
/*!
\brief Binary logarithm with 7 iterations
\param x
\return log2(x)/64
*/
/************************************************************************/
Word32 BASOP_Util_Log2(Word32 x);
/************************************************************************/
/*!
\brief Binary power
Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen
Version with 3 table lookup and 1 linear interpolations
Algorithm: compute power of 2, argument x is in Q7.25 format
result = 2^(x/64)
We split exponent (x/64) into 5 components:
integer part: represented by b31..b25 (exp)
fractional part 1: represented by b24..b20 (lookup1)
fractional part 2: represented by b19..b15 (lookup2)
fractional part 3: represented by b14..b10 (lookup3)
fractional part 4: represented by b09..b00 (frac)
=> result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp
Due to the fact, that all lookup values contain a factor 0.5
the result has to be shifted by 3 to the right also.
Table exp2_tab_long contains the log2 for 0 to 1.0 in steps
of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps
of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in
steps of 1/32768. Since the 2-logarithm of very very small
negative value is rather linear, we can use interpolation.
Limitations:
For x <= 0, the result is fractional positive
For x > 0, the result is integer in range 1...7FFF.FFFF
For x < -31/64, we have to clear the result
For x = 0, the result is ~1.0 (0x7FFF.FFFF)
For x >= 31/64, the result is 0x7FFF.FFFF
\param x
\return pow(2,(x/64))
*/
/************************************************************************/
Word32 BASOP_Util_InvLog2(Word32 x);
Word16 BASOP_util_norm_s_bands2shift (Word16 x);
/***********************************************************************/
/*!
\brief Calculate the headroom of the complex data in a 2 dimensional array
\return number of headroom bits
*/
Word16 BASOP_util_norm_l_dim2_cplx (const Word32 * const *re, /*!< Real part of 32 Bit input */
const Word32 * const *im, /*!< Imag part if 32 Bit input */
Word16 startBand, /*!< start band of cplx data */
Word16 stopBand, /*!< stop band of cplx data */
Word16 startSlot, /*!< start slot of cplx data */
Word16 stopSlot /*!< stop slot of cplx data */
);
/****************************************************************************/
/*!
\brief Does a data copy of Word8 *arg1 to Word8 *arg2 with Word16 arg3 number of moves
*/
void copyWord8( const Word8 *src, /*!< i : Source address */
Word8 *dst, /*!< i : Destination address */
const Word32 n); /*!< i : Number of elements to copy */
/****************************************************************************/
/*!
\brief Sets Word8 array arg1[] to zero for a length of Word16 arg2 elements
*/
void set_zero_Word8( Word8 X[], /*!< i : Address of array */
Word32 n); /*!< i : Number of elements to set to zero */
/****************************************************************************/
/*!
\brief Does a multiplication of Word32 * Word16 input values
\return z32 = x32 * y16
*/
Word32 L_mult0_3216( Word32 x, /*!< : Multiplier */
Word16 y); /*!< : Multiplicand */
/* Calculate sin/cos. Angle in 2Q13 format, result has exponent = 1 */
Word16 getCosWord16(Word16 theta);
Word32 getCosWord32(Word32 theta);
/**
* \brief calculate cosine of angle. Tuned for ISF domain.
* \param theta Angle normalized to radix 2, theta = (angle in radians)*2.0/pi
* \return result with exponent 0.
*/
Word16 getCosWord16R2(Word16 theta);
/****************************************************************************/
/*!
\brief square root abacus algorithm
\return integer sqrt(x)
*/
Word16 getSqrtWord32(Word32 x);
/****************************************************************************/
/*!
\brief finds index of min Word16 in array
\return index of min Word16
*/
Word16 findIndexOfMinWord16(Word16 *x, const Word16 len);
/****************************************************************************/
/*!
\brief finds index of min Word32 in array
\return index of min Word32
*/
Word16 findIndexOfMinWord32(Word32 *x, const Word16 len);
/****************************************************************************/
/*!
\brief finds index of max Word16 in array
\return index of max Word16
*/
Word16 findIndexOfMaxWord16(Word16 *x, const Word16 len);
/****************************************************************************/
/*!
\brief finds index of max Word32 in array
\return index of max Word32
*/
Word16 findIndexOfMaxWord32(Word32 *x, const Word16 len);
/****************************************************************************/
/*!
\brief 16x16->16 integer multiplication without overflow control
\return 16x16->16 integer
*/
Word16 imult1616(Word16 x, Word16 y);
/****************************************************************************/
/*!
\brief 32x16->32 integer multiplication with overflow control
\return 32x16->32 integer
*/
Word32 imult3216(Word32 x, Word16 y);
/****************************************************************************/
/*!
\brief 16/16->16 unsigned integer division
x and y have to be positive, x has to be < 16384
\return 16/16->16 integer
*/
Word16 idiv1616U(Word16 x, Word16 y);
/****************************************************************************/
/*!
\brief 16/16->16 signed integer division
x and y have to be positive, x has to be < 16384
\return 16/16->16 integer
*/
Word16 idiv1616(Word16 x, Word16 y);
/*------------------------------------------------------------------*
* Dot_product16HQ:
*
* \brief Compute scalar product of <x[],y[]> using 64-bit accumulator.
*
* Performs normalization of the result, returns the exponent
* Note: In contrast to dotWord32, no headroom is required for data
* in x[] and y[], means, they may have any format Qn
*------------------------------------------------------------------*/
Word32 Dot_product16HQ( /*<! o : normalized result Q31 */
const Word32 L_off, /*<! i : initial sum value Qn */
const Word16 x[], /*<! i : x vector Qn */
const Word16 y[], /*<! i : y vector Qn */
const Word16 lg, /*<! i : vector length, range [0..7FFF] Q0 */
Word16 * exp /*<! o : exponent of result in [-32,31] Q0 */
);
/*------------------------------------------------------------------*
* norm_llQ31:
*
* \brief Compute normalized Q31 Values out of overflowed Q31 value
*
* Performs the calculation of a normalized Q31 Value with its
* scalingfactor, taking into account the overflowed Q31 input value
* and the number of Carrys, collected.
*------------------------------------------------------------------*/
Word32 norm_llQ31( /* o : normalized result Q31 */
Word32 L_c, /* i : upper bits of accu Q-1 */
Word32 L_sum, /* i : lower bits of accu, unsigned Q31 */
Word16 * exp /* o : exponent of result in [-32,31] Q0 */
);
/**
* \brief Compute dot product of 1 32 bit vectors with itself
* \param x input vector 1
* \param headroom amount of headroom bits the input vector
* \param length the length of the input vector
* \param result_e pointer to where the exponent of the result will be stored into
* \return the dot product of x and x.
*/
Word32 Norm32Norm(const Word32 *x, const Word16 headroom, const Word16 length, Word16 *result_e);
/*------------------------------------------------------------------*
* Dot_productSq16HQ:
*
* \brief Compute scalar product of <x[],x[]> using 64-bit accumulator.
*
* Performs normalization of the result, returns the exponent
* Note: In contrast to dotWord32, no headroom is required for data
* in x[], means, they may have any format Qn
*------------------------------------------------------------------*/
Word32 Dot_productSq16HQ( /*<! o : normalized result Q31 */
const Word32 L_off, /*<! i : initial sum value Qn */
const Word16 x[], /*<! i : x vector Qn */
const Word16 lg, /*<! i : vector length, range [0..7FFF] Q0 */
Word16 * exp /*<! o : exponent of result in [-32,31] Q0 */
);
/*------------------------------------------------------------------*
* dotp_s_fx:
*
* \brief Compute scalar product of <x[],y[]> using 64-bit accumulator.
*
* Performs no normalization of the result
*------------------------------------------------------------------*/
Word32 dotp_s_fx( /*<! o : dot product of vector x and y 16Q15 */
const Word16 *x, /*<! i : vector x 6Q9 */
const Word16 *y, /*<! i : vector y 6Q9 */
const Word16 n, /*<! i : vector length Q0 */
Word16 s /*<! i : headroom Q0 */
);
/*-------------------------------------------------------------------*
* Sum32:
*
* \brief Return the sum of one 32 bits vector
*-------------------------------------------------------------------*/
Word32 Sum32( /*<! o : the sum of the elements of the vector */
const Word32 *vec, /*<! i : input vector */
const Word16 lvec /*<! i : length of input vector */
);
/**
* \brief return 2 ^ (exp * 2^exp_e)
* \param exp_m mantissa of the exponent to 2.0f
* \param exp_e exponent of the exponent to 2.0f
* \param result_e pointer to a INT where the exponent of the result will be stored into
* \return mantissa of the result
*/
Word32 BASOP_util_Pow2(
const Word32 exp_m, const Word16 exp_e,
Word16 *result_e
);
/* deprecated, use ISqrt32norm! */
Word32 Isqrt_lc(
Word32 frac, /*!< (i) Q31: normalized value (1.0 < frac <= 0.5) */
Word16 * exp /*!< (i/o) : exponent (value = frac x 2^exponent) */
);
/**
* \brief return 1/x
* \param x index of lookup table
* \return Word16 value of 1/x
*/
Word16 getNormReciprocalWord16(Word16 x);
/**
* \brief return (1/x) << s
* \param x index of lookup table
* \param s shift factor
* \return Word16 value of (1/x) << s
*/
Word16 getNormReciprocalWord16Scale(Word16 x, Word16 s);
/*************************************************************************
*
* FUNCTION: BASOP_Util_fPow()
*/
/**
* \brief BASOP_Util_fPow
*
* PURPOSE: Computes pow(base_m, base_e, exp_m, exp_e), where base_m and base_e
* specify the base, and exp_m and exp_e specify the exponent.
* The result is returned in a mantissa and exponent representation.
*
* DESCRIPTION:
* The function BASOP_Util_fPow(L_x) calculates the power function by
* calculating 2 ^ (log2(base)*exp)
*
* \param base_m mantissa of base
* \param base_e exponent of base
* \param exp_m mantissa of exponent
* \param exp_e exponent of exponent
* \param result_e pointer to exponent of result
* \return Word32 mantissa of result
*
*************************************************************************/
Word32 BASOP_Util_fPow( /* (o) : mantissa of result */
Word32 base_m, Word16 base_e, /* (i) : input value for base (mantissa and exponent) */
Word32 exp_m, Word16 exp_e, /* (i) : input value for exponent (mantissa and exponent) */
Word16 *result_e /* (o) : output pointer to exponent of result */
);
/*___________________________________________________________________________
| |
| Function Name : Dot_product12_offs() |
| |
| Compute scalar product of <x[],y[]> using accumulator. |
| The parameter 'L_off' is added to the accumulation result. |
| The result is normalized (in Q31) with exponent (0..30). |
| Notes: |
| o data in x[],y[] must provide enough headroom for accumulation |
| o L_off must correspond in format with product of x,y |
| Example: 0.01f for Q9 x Q9: 0x0000147B in Q19 |
| means: L_off = FL2WORD32_SCALE(0.01f,31-19) |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| dot_product = L_off + sum(x[i]*y[i]) i=0..N-1 |
|___________________________________________________________________________|
*/
Word32 Dot_product12_offs( /* (o) Q31: normalized result (1 < val <= -1) */
const Word16 x[], /* (i) 12bits: x vector */
const Word16 y[], /* (i) 12bits: y vector */
const Word16 lg, /* (i) : vector length in range [1..256] */
Word16 * exp, /* (o) : exponent of result (0..+30) */
Word32 L_off /* (i) initial summation offset /2 */
);
Word32 Dot_product15_offs( /* (o) Q31: normalized result (1 < val <= -1) */
const Word16 x[], /* (i) 15bits: x vector */
const Word16 y[], /* (i) 15bits: y vector */
const Word16 lg, /* (i) : vector length in range [1..256] */
Word16 *exp, /* (o) : exponent of result (0..+30) */
Word32 L_off /* (i) initial summation offset */
);
/*!**********************************************************************
\brief Add two values given by mantissa and exponent.
Mantissas are in 32-bit-fractional format with values between 0 and 1. <br>
The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
************************************************************************/
Word32 BASOP_Util_Add_Mant32Exp /*!< o: normalized result mantissa */
(Word32 a_m, /*!< i: Mantissa of 1st operand a */
Word16 a_e, /*!< i: Exponent of 1st operand a */
Word32 b_m, /*!< i: Mantissa of 2nd operand b */
Word16 b_e, /*!< i: Exponent of 2nd operand b */
Word16 *ptr_e); /*!< o: exponent of result */
/*!**********************************************************************
\brief Returns the comparison result of two normalized values given by mantissa and exponent.
return value: -1: a < b, 0: a == b, 1; a > b
Mantissas are in 32-bit-fractional format with values between 0 and 1. <br>
The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$<br>
************************************************************************/
Word16 BASOP_Util_Cmp_Mant32Exp /*!< o: flag: result of comparison */
(Word32 a_m, /*!< i: Mantissa of 1st operand a */
Word16 a_e, /*!< i: Exponent of 1st operand a */
Word32 b_m, /*!< i: Mantissa of 2nd operand b */
Word16 b_e); /*!< i: Exponent of 2nd operand b */
/********************************************************************
* bufferCopyFx
*
* \brief copies buffer while preserving Format of destination buffer
*********************************************************************
*/
void bufferCopyFx(
Word16* src, /*<! Qx pointer to input buffer */
Word16* dest, /*<! Qx pointer to output buffer */
Word16 length, /*<! Q0 length of buffer to copy */
Word16 Qf_src, /*<! Q0 Q format (frac-bits) of source buffer */
Word16 Qf_dest, /*<! Q0 Q format (frac-bits )of dest buffer */
Word16 Q_src, /*<! Q0 exponent of source buffer */
Word16 Q_dest /*<! Q0 exponent of destination buffer */
);
/****************************************************************************/
/*!
\brief Accumulates multiplications
Accumulates the elementwise multiplications of Word32 Array bufX32 with Word16 Array bufY16
pointed to by arg1 to arg4 including the corresponding exponents. Length of to be multiplied arrays is arg5,
\return Word32 result of accumulated multiplications over Word32 array arg1 and Word16 array arg3 and Word16 pointer
to exponent of the result
*/
Word32 dotWord32_16_Mant32Exp(const Word32 *bufX32,/* i: 32-bit buffer with unknown headroom */
Word16 bufX32_exp, /* i: exponent of buffer bufX32 */
const Word16 *bufY16,/* i: 16-bit buffer quite right-aligned */
Word16 bufY16_exp, /* i: exponent of buffer bufY16 */
Word16 len, /* i: buffer len to process */
Word16 *exp); /* o: result exponent */
/*!**********************************************************************
\brief Converts linear factor or energy to Decibel
return value: fEnergy=0: 20 * log10(x * 2^{x\_e}),
fEnergy=1: 10 * log10(x * 2^{x\_e})
Mantissa x is in 32-bit-fractional format with values between 0 and 1. <br>
The base for exponent x_e is 2. <br>
************************************************************************/
Word16 BASOP_Util_lin2dB( /*!< o: dB value (7Q8) */
Word32 x, /*!< i: mantissa */
Word16 x_e, /*!< i: exponent */
Word16 fEnergy); /*!< i: flag indicating if x is energy */
/*!**********************************************************************
\brief Calculates atan(x).
************************************************************************/
Word16 BASOP_util_atan( /*!< o: atan(x) [-pi/2;pi/2] 1Q14 */
Word32 x /*!< i: input data (-64;64) 6Q25 */
);
/*!**********************************************************************
\brief Calculates atan2(y,x).
************************************************************************/
Word16 BASOP_util_atan2( /*!< o: atan2(y,x) [-pi,pi] Q13 */
Word32 y, /*!< i: */
Word32 x, /*!< i: */
Word16 e /*!< i: exponent difference (exp_y - exp_x) */
);
/*!**********************************************************************
\brief norm_llQ31 returns Word32 with scalingfactor, with 2 32bit accus as input
************************************************************************/
Word32 norm_llQ31( /* o : normalized result Q31 */
Word32 L_c, /* i : upper bits of accu Q-1 */
Word32 L_sum, /* i : lower bits of accu, unsigned Q31 */
Word16 * exp /* o : exponent of result in [-32,31] Q0 */
);
/* compare two positive normalized 16 bit mantissa/exponent values */
/* return value: positive if first value greater, negative if second value greater, zero if equal */
Word16 compMantExp16Unorm(Word16 m1, Word16 e1, Word16 m2, Word16 e2);
#endif /* __BASOP_UTIL_H__ */
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* Common constants */
/*--------------------------------------------------------------------------
* bitallocsum_fx()
*
* Calculate the total number of bits allocated over frame
*--------------------------------------------------------------------------*/
void bitallocsum_fx(
Word16 *R, /* i : bit-allocation vector Q0 */
const Word16 nb_sfm, /* i : number of sub-vectors Q0 */
Word16 *sum, /* o : total number of bits allocated Q0 */
Word16 *Rsubband, /* o : rate per subband Q3 */
const Word16 v, /* i : bit rate Q0 */
const Word16 length, /* i : length of spectrum (32 or 48 kHz samplerate) Q0 */
const Word16 *sfmsize /* i : band length Q0 */
)
{
Word16 i;
Word16 total, tmp;
Word16 diff;
total = (Word16)0;
move16();
FOR (i = 0; i < nb_sfm; i++)
{
tmp = extract_l(L_mult0(R[i], sfmsize[i]));
Rsubband[i] = shl(tmp, 3);
move16();
total = add(total, tmp);
}
*sum = total;
IF ( sub(length, L_FRAME32k) <= 0 )
{
diff = sub(v, *sum);
i = (Word16)0;
move16();
WHILE ( diff > 0 )
{
IF ( R[i] > 0 )
{
Rsubband[i] = add(Rsubband[i], 8);
move16();
diff = sub(diff, 1);
*sum = add(*sum, 1);
}
i = add(i, 1);
if ( sub(i, nb_sfm) >= 0 )
{
i = (Word16)0;
move16();
}
}
}
return;
}
+384
View File
@@ -0,0 +1,384 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include <assert.h>
#include "options.h"
#include "prot_fx.h"
#include "basop_util.h"
#include "stl.h"
#include "options.h"
#include "rom_com_fx.h"
/*
* function BITS_ALLOC_init_config_acelp()
*
* description: initial configuration for ACELP
*
* return: void
*/
void BITS_ALLOC_init_config_acelp(
const Word32 bit_rate,
const Word8 narrowBand,
const Word16 nb_subfr,
ACELP_config *pConfigAcelp /*o: configuration structure of ACELP*/
)
{
Word8 rate_mode_index;
move16();
move16();
move16();
rate_mode_index=(bit_rate > ACELP_9k60);
pConfigAcelp->mode_index=rate_mode_index;
/*LPC: midLpc should be swithced off?*/
pConfigAcelp->midLpc_enable = 1;
move16();
/*ACELP ICB config*/
test();
IF( (rate_mode_index==0) || narrowBand != 0 )
{
move16();
move16();
move16();
move16();
move16();
move16();
pConfigAcelp->pre_emphasis = 1;
pConfigAcelp->formant_enh = 1;
pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1;
pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2;
pConfigAcelp->formant_tilt = 0;
pConfigAcelp->voice_tilt = 0;
}
ELSE
{
move16();
move16();
move16();
move16();
move16();
move16();
pConfigAcelp->pre_emphasis = 0;
pConfigAcelp->formant_enh = 1;
pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1;
pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2;
pConfigAcelp->formant_tilt = 1;
pConfigAcelp->voice_tilt = 1;
}
/*Wide band @ 16kHz*/
IF ( sub(nb_subfr,NB_SUBFR16k) == 0 )
{
move16();
move16();
move16();
move16();
move16();
move16();
pConfigAcelp->pre_emphasis = 1;
pConfigAcelp->formant_enh = 1;
pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1_16k;
pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2_16k;
pConfigAcelp->formant_tilt = 0;
pConfigAcelp->voice_tilt = 2;
}
}
/*
* function BITS_ALLOC_config_acelp()
*
* description: configure all acelp modes and allocate the bits
*
* return: bit demand
*/
Word16 BITS_ALLOC_config_acelp(
const Word16 bits_frame, /*i: remaining bit budget for the frame*/
const Word16 coder_type, /*i: acelp coder type*/
ACELP_config *pConfigAcelp, /*i/o: configuration structure of ACELP*/
const Word16 narrowBand,
const Word16 nb_subfr
)
{
Word16 mode_index;
Word16 band_index;
Word16 i;
Word16 remaining_bits, bits;
move16();
move16();
move16();
mode_index = pConfigAcelp->mode_index;
band_index = (narrowBand==0);
bits=0;
IF ( band_index==0 )
{
move16();
pConfigAcelp->formant_enh = 1;
if(sub(coder_type,INACTIVE) == 0)
{
move16();
pConfigAcelp->formant_enh = 0;
}
}
IF ( s_and(sub(band_index,1)==0, sub(nb_subfr,4)==0) )
{
IF(sub(coder_type,INACTIVE) == 0)
{
pConfigAcelp->pre_emphasis = 0;
move16();
pConfigAcelp->formant_enh = 0;
move16();
pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1_16k;
move16();
pConfigAcelp->voice_tilt = 1;
move16();
pConfigAcelp->formant_tilt = 1;
move16();
}
ELSE
{
pConfigAcelp->pre_emphasis = 1;
move16();
pConfigAcelp->formant_enh = 1;
move16();
pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1;
move16();
pConfigAcelp->voice_tilt = 0;
move16();
pConfigAcelp->formant_tilt = 0;
move16();
}
}
IF (sub(coder_type,UNVOICED) == 0 )
{
IF(sub(ACELP_GAINS_MODE[mode_index][band_index][coder_type], 6) == 0)
{
pConfigAcelp->pitch_sharpening = 0;
move16();
pConfigAcelp->phase_scrambling = 1;
move16();
}
ELSE
{
pConfigAcelp->pitch_sharpening = 0;
move16();
pConfigAcelp->phase_scrambling = 0;
move16();
}
}
ELSE
{
pConfigAcelp->pitch_sharpening = 1;
move16();
pConfigAcelp->phase_scrambling = 0;
move16();
}
IF(sub(coder_type,ACELP_MODE_MAX) > 0) /* keep pitch sharpening for RF_ALLPRED mode */
{
pConfigAcelp->pitch_sharpening = 0;
pConfigAcelp->phase_scrambling = 0;
}
/*Allocate bits and different modes*/
move16();
pConfigAcelp->bpf_mode=ACELP_BPF_MODE[mode_index][band_index][coder_type];
bits = add(bits, ACELP_BPF_BITS[pConfigAcelp->bpf_mode]);
move16();
move16();
pConfigAcelp->nrg_mode=ACELP_NRG_MODE[mode_index][band_index][coder_type];
pConfigAcelp->nrg_bits=ACELP_NRG_BITS[pConfigAcelp->nrg_mode];
bits = add(bits, pConfigAcelp->nrg_bits);
move16();
pConfigAcelp->ltp_mode=ACELP_LTP_MODE[mode_index][band_index][coder_type];
move16();
pConfigAcelp->ltp_bits=0;
move16();
pConfigAcelp->ltf_mode=ACELP_LTF_MODE[mode_index][band_index][coder_type];
move16();
pConfigAcelp->ltf_bits=ACELP_LTF_BITS[pConfigAcelp->ltf_mode];
if ( s_and(sub(nb_subfr,5)==0, sub(pConfigAcelp->ltf_bits,4)==0) )
{
pConfigAcelp->ltf_bits = add(pConfigAcelp->ltf_bits,1);
}
bits = add(bits,pConfigAcelp->ltf_bits);
FOR ( i=0; i<nb_subfr; i++ )
{
pConfigAcelp->gains_mode[i] = ACELP_GAINS_MODE[mode_index][band_index][coder_type];
move16();
/* skip subframe 1, 3 gain encoding, and use from subframe 0, and 3, respectively */
test();
test();
IF(sub(coder_type,ACELP_MODE_MAX) >= 0 && (sub(i,1) == 0 || sub(i,3) == 0))
{
pConfigAcelp->gains_mode[i] = 0;
}
bits = add(bits, ACELP_GAINS_BITS[pConfigAcelp->gains_mode[i]]);
move16();
bits = add(bits, ACELP_LTP_BITS_SFR[pConfigAcelp->ltp_mode][i]);
pConfigAcelp->ltp_bits= add( pConfigAcelp->ltp_bits,ACELP_LTP_BITS_SFR[pConfigAcelp->ltp_mode][i]);
}
/*Innovation*/
if ( sub(bits_frame,bits) < 0)
{
printf("Warning: bits per frame too low\n");
return -1;
}
IF( sub(coder_type,RF_ALLPRED) == 0 )
{
set16_fx(pConfigAcelp->fixed_cdk_index, -1, nb_subfr);
}
ELSE IF ( sub(coder_type,RF_GENPRED) == 0 )
{
pConfigAcelp->fixed_cdk_index[0] = 0; /* 7 bits */
pConfigAcelp->fixed_cdk_index[1] = -1;
pConfigAcelp->fixed_cdk_index[2] = 0; /* 7 bits */
pConfigAcelp->fixed_cdk_index[3] = -1;
pConfigAcelp->fixed_cdk_index[4] = -1;
bits = add(bits,14);
}
ELSE IF( sub(coder_type,RF_NOPRED) == 0 )
{
set16_fx(pConfigAcelp->fixed_cdk_index, 0, nb_subfr);
bits = add(bits,28);
}
ELSE
{
bits = add(bits, BITS_ALLOC_adjust_acelp_fixed_cdk(sub(bits_frame,bits), pConfigAcelp->fixed_cdk_index, nb_subfr ));
}
remaining_bits = sub(bits_frame, bits);
/*Sanity check*/
if (remaining_bits<0)
{
move16();
bits = -1;
}
return(bits);
}
static
Word16 BITS_ALLOC_adjust_generic(
const Word16 bits_frame, /*i: bit budget*/
Word16 *fixed_cdk_index,
const Word16 nb_subfr,
const Word16 *pulseconfigbits,
const Word16 pulseconfig_size
)
{
Word16 bits_subframe2, inb_subfr;
Word16 sfr, k, bitsused, bits_currsubframe;
bits_subframe2 = bits_frame;
move16();
inb_subfr = 8192/*1.0f/NB_SUBFR Q15*/;
move16();
if ( sub(nb_subfr,NB_SUBFR16k) == 0 )
{
inb_subfr = 6554/*1.0f/NB_SUBFR16k Q15*/;
move16();
}
IF ( sub(bits_subframe2, i_mult2(pulseconfigbits[0], nb_subfr)) < 0 ) /* not in final code - not instrumented */
{
return add(bits_frame,1); /* Not enough bits for lowest mode. -> trigger alarm*/
}
/* search cdk-index for first subframe */
FOR (k=0; k<pulseconfig_size-1; k++)
{
IF (i_mult2(pulseconfigbits[k], nb_subfr) > bits_subframe2)
{
k = sub(k,1); /* previous mode did not exceed bit-budget */
BREAK;
}
}
if (i_mult2(pulseconfigbits[k], nb_subfr) > bits_subframe2)
{
k = sub(k,1); /* previous mode did not exceed bit-budget */
}
move16();
fixed_cdk_index[0] = k;
bitsused = i_mult2(pulseconfigbits[k], nb_subfr);
FOR (sfr=1; sfr < nb_subfr; sfr++)
{
/*bits_currsubframe = (int)(((float)sfr+1.0f)*bits_subframe) - bitsused;*/
bits_currsubframe = sub(add(i_mult2(sfr, bits_subframe2), bits_subframe2), bitsused);
/* try increasing mode while below threshold */
WHILE ( (sub(k, pulseconfig_size-1) < 0) && (sub(i_mult2(pulseconfigbits[add(k,1)], nb_subfr),bits_currsubframe) <= 0) )
{
test();
k = add(k,1);
}
/* try decreasing mode until below threshold */
WHILE (i_mult2(pulseconfigbits[k], nb_subfr) > bits_currsubframe)
{
k = sub(k,1);
IF (k == 0)
{
BREAK;
}
}
/* store mode */
move16();
fixed_cdk_index[sfr] = k;
bitsused = add(bitsused, i_mult2(pulseconfigbits[k], nb_subfr));
}
return mult_r(bitsused, inb_subfr);
}
Word16 BITS_ALLOC_adjust_acelp_fixed_cdk(
const Word16 bits_frame, /*i: bit budget*/
Word16 *fixed_cdk_index,
const Word16 nb_subfr
)
{
Word16 bitsused;
bitsused = BITS_ALLOC_adjust_generic(bits_frame, fixed_cdk_index, nb_subfr, ACELP_CDK_BITS, ACELP_FIXED_CDK_NB);
return bitsused;
}
File diff suppressed because it is too large Load Diff
+134
View File
@@ -0,0 +1,134 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* */
#include "stl.h"
/*
* E_GAIN_f_pitch_sharpening
*
* Parameters:
* x I/O: impulse response (or algebraic code)
* pit_lag I: pitch lag
*
* Function:
* Performs Pitch sharpening routine for one subframe.
* pitch sharpening factor is 0.85
*
* Returns:
* void
*/
static void E_GAIN_f_pitch_sharpening(Word16 *x, Word16 pit_lag, Word16 L_subfr)
{
Word16 i, tmp;
FOR (i = pit_lag; i < L_subfr; i++)
{
/*x[i] += x[i - pit_lag] * F_PIT_SHARP;*/
tmp = mult_r(x[i - pit_lag], 27853/*F_PIT_SHARP Q15*/);
x[i] = add(x[i],tmp);
move16();
}
return;
}
/*-------------------------------------------------------------------*
* cb_shape()
*
* pre-emphasis, pitch sharpening and formant sharpening of the algebraic codebook
*-------------------------------------------------------------------*/
void cb_shape_fx(
const Word16 preemphFlag, /* i : flag for pre-emphasis */
const Word16 pitchFlag, /* i : flag for pitch sharpening */
const Word16 scramblingFlag, /* i : flag for phase scrambling */
const Word16 sharpFlag, /* i : flag for formant sharpening */
const Word16 formantTiltFlag, /* i : flag for formant tilt */
const Word16 g1, /* i : formant sharpening numerator weighting */
const Word16 g2, /* i : formant sharpening denominator weighting */
const Word16 *p_Aq, /* i : LP filter coefficients */
Word16 *code, /* i/o: signal to shape */
const Word16 tilt_code, /* i : tilt of code */
const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch */
const Word16 shift
)
{
Word16 tmp, buff[L_SUBFR+M], A_num[M+1], A_den[M+1];
Word16 i;
Word32 L_tmp;
Word16 tilt, mu;
tmp = 0;
move16();
/* Pre-emphasis */
IF( preemphFlag )
{
preemph_copy_fx(code, code, tilt_code, L_SUBFR, &tmp);
}
/* pitch sharpening */
IF( pitchFlag )
{
E_GAIN_f_pitch_sharpening( code, pt_pitch, L_SUBFR );
}
/* phase scrambling filter */
IF( scramblingFlag )
{
buff[0] = code[0];
move16();
FOR (i = 1; i < L_SUBFR; i++)
{
buff[i]=code[i];
move16();
/*code[i] = 0.7f*buff[i] + buff[i-1] - 0.7f*code[i-1]; */
L_tmp = L_mult(22938, buff[i]);
tmp = mac_r(L_tmp,-22938, code[i-1]);
code[i] = add(tmp,buff[i-1]);
move16();
}
}
test();
IF ( sharpFlag || formantTiltFlag )
{
weight_a_fx( p_Aq, A_num, g1, M );
weight_a_fx( p_Aq, A_den, g2, M );
set16_fx(buff, 0, M+L_SUBFR);
IF( formantTiltFlag )
{
Copy(A_num, buff+M, M+1);
E_UTIL_synthesis(1, A_den, buff+M, buff+M, L_SUBFR, buff, 0, M);
/*Compute tilt of formant enhancement*/
tilt = extract_l(L_shr(get_gain(buff+M+1, buff+M, L_SUBFR-1),1));
/*Combine tilt of code and fe*/
tmp = 0;
move16();
/*mu = 0.5f*tilt_code-0.25f*tilt;*/
mu = sub(shr(tilt_code,1),shr(tilt,2));
preemph_copy_fx(code, code, mu, L_SUBFR, &tmp);
}
ELSE
{
Copy( code, buff, L_SUBFR );
Overflow = 0;
move16();
Residu3_lc_fx(A_num, M, buff, code, L_SUBFR, shift);
{
syn_filt_s_lc_fx(shift, A_den, code, code, L_SUBFR);
}
}
}
return;
}
+1701
View File
File diff suppressed because it is too large Load Diff
+889
View File
@@ -0,0 +1,889 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#include "rom_com_fx.h"
/*---------------------------------------------------------------------*
* Local constants
*---------------------------------------------------------------------*/
#define A2 6554
#define OmA2 (32768-A2)
#define GAIN_VAR 11811 /* in Q31 divided by 2 (Q30) */
/*-------------------------------------------------------*
* CNG_exc()
*
* Comfort noise generation routine
*-------------------------------------------------------*/
void CNG_exc_fx(
const Word32 core_brate, /* i : core bitrate */
const Word16 L_frame, /* i : length of the frame */
Word32 *Enew, /* i/o: decoded SID energy Q6 */
Word16 *seed, /* i/o: random generator seed */
Word16 exc[], /* o : current non-enhanced excitation Q_new */
Word16 exc2[], /* o : current enhanced excitation Q_new */
Word32 *lp_ener, /* i/o: LP filtered E */
const Word32 last_core_brate, /* i : previous frame core bitrate */
Word16 *first_CNG, /* i/o: first CNG frame flag for energy init. */
Word16 *cng_ener_seed, /* i/o: random generator seed for CNG energy */
Word16 bwe_exc[], /* o : excitation for SWB TBE */
const Word16 allow_cn_step, /* i : allow CN step */
Word16 *last_allow_cn_step, /* i/o: last allow step */
const Word16 OldQ_exc, /* i : Old excitation scaling */
const Word16 Q_exc /* i : excitation scaling */
, const Word16 num_ho /* i : number of selected hangover frames */
,Word32 q_env[]
,Word32 *lp_env
,Word32 *old_env
,Word16 *exc_mem
,Word16 *exc_mem1
,Word16 *sid_bw
,Word16 *cng_ener_seed1
,Word16 exc3[]
,Word16 Opt_AMR_WB
)
{
Word16 i, tmp, tmp2, exp, exp2, Q_ener;
Word32 L_tmp_ener, L_tmp;
Word16 i_subfr;
Word16 pit_max;
Word16 ftmp,j;
Word16 *ptR,*ptI;
Word16 fft_io[L_FRAME16k];
Word32 itmp[129];
Word32 env[NUM_ENV_CNG];
Word32 enr1;
Word32 denv[NUM_ENV_CNG];
Word16 fra;
Word16 temp_lo_fx, temp_hi_fx;
Word16 exp_pow;
Word32 L_tmp2;
Word16 *pt_fft_io;
/*------------------------------------------------------------------*
* Initializations
*------------------------------------------------------------------*/
pit_max = PIT16k_MAX;
move16();
if( sub(L_frame,L_FRAME) == 0 )
{
pit_max = PIT_MAX;
move16();
}
/*---------------------------------------------------------------------*
* Initialization of CNG energy for the first CNG frame
*---------------------------------------------------------------------*/
IF(*first_CNG == 0 )
{
IF(L_sub(core_brate,FRAME_NO_DATA) == 0 )
{
/* needed only in decoder when the very first SID frame was erased and this frame is FRAME_NO_DATA frame */
/*fenew = dotp( fexc, fexc, pit_max )/pit_max;*/
L_tmp_ener = Calc_Energy_Autoscaled(exc-pit_max, OldQ_exc, pit_max, &Q_ener);
L_tmp_ener = Mult_32_16(L_tmp_ener, 9079); /* divide by PIT_MAX (in Q15 + Q6 to get output in Q6)*/
L_tmp_ener = L_shr(L_tmp_ener, Q_ener); /* -> If we want ener in Q6 */
if(sub(L_frame, L_FRAME16k) == 0)
{
L_tmp_ener = Mult_32_16(L_tmp_ener, 26214); /* Compensate for 16kHz */
}
*Enew = L_tmp_ener;
move32();
}
*lp_ener = *Enew;
move32();
}
/*---------------------------------------------------------------------*
* Update CNG energy
*---------------------------------------------------------------------*/
test();
test();
IF( L_sub(last_core_brate,SID_1k75) != 0 && L_sub(last_core_brate,FRAME_NO_DATA) != 0 && L_sub(last_core_brate,SID_2k40) != 0 )
{
/* Partially reset CNG energy after active speech period */
test();
IF ( allow_cn_step == 0 && *last_allow_cn_step == 0 )
{
test();
IF( sub(num_ho,3) < 0 || L_sub(Mult_32_16(*Enew,21845 /*1/1.5f, Q15*/), *lp_ener) < 0 )
{
/**lp_ener = 0.8f * *lp_ener + 0.2f * *Enew;*/
L_tmp_ener = Mult_32_16(*lp_ener, 26214);
L_tmp_ener = Madd_32_16(L_tmp_ener, *Enew, 6554);
}
ELSE
{
/**lp_ener = 0.95f * *lp_ener + 0.05f * *Enew;*/
L_tmp_ener = Mult_32_16(*lp_ener, 31130);
L_tmp_ener = Madd_32_16(L_tmp_ener, *Enew, 1638);
}
}
ELSE
{
L_tmp_ener = L_add(0,*Enew);
*last_allow_cn_step = 0;
move16();
}
}
ELSE
{
/* normal CNG update */
IF ( *last_allow_cn_step == 0 )
{
/**lp_ener = (float)(A2 * *Enew + (1-A2) * *lp_ener);*/
L_tmp_ener = Mult_32_16(*Enew, A2);
L_tmp_ener = Madd_32_16(L_tmp_ener, *lp_ener, OmA2);
}
ELSE
{
test();
if ( L_sub(core_brate,SID_1k75) == 0 || L_sub(core_brate,SID_2k40) == 0 )
{
*last_allow_cn_step = 0;
move16();
}
L_tmp_ener = *Enew;
move32();
}
}
*lp_ener = L_max(L_tmp_ener,1);
move32(); /*To avoid / per 0*/
if ( sub(allow_cn_step,1) == 0)
{
*last_allow_cn_step = 1;
move16();
}
/*---------------------------------------------------------------------*
* Generate white noise vector
*---------------------------------------------------------------------*/
/*for ( i=0; i<L_frame; i++ )exc2[i] = (float)own_random( seed );*/
Random_Fill(seed, L_frame, exc2, 4);
/*------------------------------------------------------------*
* Insert random variation for excitation energy
* (random variation is scaled according to *lp_ener value)
*------------------------------------------------------------*/
FOR ( i_subfr=0; i_subfr<L_frame; i_subfr += L_SUBFR )
{
/* ener_lp = own_random(cng_ener_seed) * *lp_ener * GAIN_VAR + *lp_ener */
/*------------------------------------------------------------*
* Insert random variation for excitation energy
* (random variation is scaled according to *lp_ener value)
*------------------------------------------------------------*/
L_tmp = Mult_32_16(*lp_ener, Random(cng_ener_seed));
L_tmp = Mult_32_16(L_tmp, GAIN_VAR);
L_tmp = L_add(L_tmp, *lp_ener);
L_tmp = L_max(L_tmp, 1);
/* enr = dot_product( exc2, exc2, L_SUBFR ) + 0.01f */
tmp = extract_h(Dot_product12(&exc2[i_subfr], &exc2[i_subfr], L_SUBFR, &exp));
exp = add(exp, 8-6); /* 8 from Q-4, -6 from L_SUBFR */
/* enr = (float)sqrt(*lp_ener * L_SUBFR / enr) */
exp2 = norm_l(L_tmp);
tmp2 = extract_h(L_shl(L_tmp, exp2));
exp2 = sub(31-6, exp2); /* in Q15 (L_tmp in Q6)*/
exp = sub(exp, exp2);
if (sub(tmp, tmp2) > 0)
{
exp = add(exp, 1);
}
if (sub(tmp, tmp2) > 0)
{
tmp = shr(tmp, 1);
}
tmp = div_s(tmp, tmp2);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp);
tmp = extract_h(L_tmp);
exp = add(exp, 4); /* From Q15 to Q19 */
exp = add(exp, Q_exc); /* Q_exc+ Q19 */
FOR (i=0; i<L_SUBFR; i++)
{
/* exc2[i] *= enr */
L_tmp = L_mult(exc2[i_subfr+i], tmp); /* Q-4 * Q_exc+19 -> Q_exc +16 */
exc2[i_subfr+i] = round_fx(L_shl(L_tmp, exp));
}
}
IF ( sub(Opt_AMR_WB,1) != 0 )
{
Copy( exc2, exc3, L_FRAME16k);
/* enr1 = (float)log10( *Enew*L_frame + 0.1f ) / (float)log10( 2.0f ); */
exp = norm_l(*Enew);
L_tmp = L_shl(*Enew,exp); /* Q(exp+6) */
L_tmp = Mult_32_16(L_tmp,shl(L_frame,5)); /* Q(exp+6+5-15=exp-4) */
L_tmp = L_shr(L_tmp,sub(exp,10)); /* Q6 */
exp = norm_l(L_tmp);
fra = Log2_norm_lc(L_shl(L_tmp,exp));
exp = sub(sub(30,exp),6);
L_tmp = L_Comp(exp,fra);
/* enr1 = round_fx(L_shl(L_tmp,8)); */ /*Q8 */
enr1 = L_shr(L_tmp,10);/* Q6 */
IF ( L_sub(core_brate,SID_2k40) == 0 )
{
IF ( *sid_bw == 0 )
{
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* get quantized envelope */
/* env[i] = pow(2.0f,(enr1 - q_env[i])); */
L_tmp = L_sub(enr1,q_env[i]);/* Q6 */
L_tmp = L_shl(L_tmp, 10);/* 16 */
temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx);
exp_pow = sub(14, temp_hi_fx);
L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */
env[i] = L_shl(L_tmp, sub(6, exp_pow));
move32();/* Q6 */
}
}
/* initialize CNG envelope */
test();
IF( *first_CNG == 0 && *sid_bw == 0 )
{
Copy32(env, lp_env, NUM_ENV_CNG);
}
IF ( *sid_bw == 0 )
{
Copy32(env, old_env, NUM_ENV_CNG);
}
}
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* get AR low-passed envelope */
/* lp_env[i] = 0.9f*lp_env[i] + (1-0.9f)*old_env[i]; */
L_tmp = Mult_32_16(lp_env[i],29491);
lp_env[i] = L_add(L_tmp,Mult_32_16(old_env[i],3277));
move32();/* Q6 */
}
/* calculate the spectrum of random excitation signal */
Copy(exc2, fft_io, L_frame);
IF ( sub(L_frame,L_FRAME16k) == 0 )
{
modify_Fs_fx( fft_io, L_FRAME16k, 16000, fft_io, 12800, exc_mem1, 0 );
}
/* fft_rel(fft_io, L_FFT, LOG2_L_FFT); */
fft_rel_fx(fft_io, L_FFT, LOG2_L_FFT);/* ??????? */
ptR = &fft_io[1];
ptI = &fft_io[sub(L_FFT,1)];
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* env[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
L_tmp = L_mult0(*ptR,*ptR);/* 2*Q_exc */
L_tmp = L_mac0(L_tmp,*ptI,*ptI);/* 2*Q_exc */
L_tmp = L_shr(L_tmp,1);/* 2*Q_exc+6 */
tmp = add(Q_exc,Q_exc);
env[i] = L_shr(L_tmp,tmp);
move32();/* Q6 */
ptR++;
ptI--;
}
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* denv[i] = lp_env[i] + 2*(*lp_ener) - env[i]; */
L_tmp = L_add(*lp_ener,*lp_ener);
denv[i] = L_sub(L_add(lp_env[i],L_tmp),env[i]);
move32();/* Q6 */
if ( denv[i] < 0 )
{
denv[i] = L_deposit_l(0);
}
}
set32_fx(itmp, 0, NUM_ENV_CNG);
set16_fx(fft_io, 0, L_FFT);
ptR = &fft_io[1];
ptI = &fft_io[sub(L_FFT,1)];
FOR (i=0; i<NUM_ENV_CNG; i++)
{
/* *ptR = own_random( cng_ener_seed1 ); */
/* *ptI = own_random( cng_ener_seed1 ); */
*ptR = Random( cng_ener_seed1 );
*ptI = Random( cng_ener_seed1 );
/* env[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
L_tmp = L_mult0(*ptR,*ptR);/* Q0 */
L_tmp = L_mac0(L_tmp,*ptI,*ptI);/* Q0 */
env[i] = L_shr(L_tmp,1);
move32(); /* Q6 */
ptR++;
ptI--;
}
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* itmp[i] += own_random( cng_ener_seed1 )*denv[i]*0.000011f + denv[i]; */
L_tmp = Mult_32_16(denv[i], Random(cng_ener_seed1));
L_tmp = Mult_32_16(L_tmp, GAIN_VAR);
L_tmp = L_add(L_tmp, denv[i]);
itmp[i] = L_add(L_tmp, itmp[i]);
move32();/* Q6 */
if (itmp[i] < 0)
{
itmp[i] = L_deposit_l(0);
}
}
ptR = &fft_io[1];
ptI = &fft_io[sub(L_FFT,1)];
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
/* *ptR *= sqrt(itmp[i]/env[i]); */
/* *ptI *= sqrt(itmp[i]/env[i]); */
L_tmp = L_max(1, itmp[i]); /*Q6*/
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
exp = sub(31-6, exp); /* in Q15 (L_tmp in Q6)*/
exp2 = norm_l(env[i]);
tmp2 = extract_h(L_shl(env[i], exp2));
exp2 = sub(31-6, exp2); /* in Q15 (L_tmp in Q6)*/
exp = sub(exp2, exp); /* Denormalize and substract */
if (sub(tmp2, tmp) > 0)
{
exp = add(exp, 1);
}
if (sub(tmp2, tmp) > 0)
{
tmp2 = shr(tmp2, 1);
}
tmp = div_s(tmp2, tmp);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp)*/
L_tmp2 = Mult_32_16(L_tmp,*ptR);/*Q(16-exp)*/
*ptR = extract_h(L_shl(L_tmp2,add(exp,Q_exc))); /*Q_exc*/
L_tmp2 = Mult_32_16(L_tmp,*ptI);/*Q(16-exp)*/
*ptI = extract_h(L_shl(L_tmp2,add(exp,Q_exc))); /*Q_exc*/
ptR++;
ptI--;
}
ifft_rel_fx(fft_io, L_FFT, LOG2_L_FFT);
IF ( sub(L_frame,L_FRAME16k) == 0 )
{
modify_Fs_fx( fft_io, L_FFT, 12800, fft_io, 16000, exc_mem, 0 );
}
/* enr1 = dotp( fft_io, fft_io, L_frame ) / L_frame; */
enr1 = L_deposit_l(1);
pt_fft_io = fft_io;
IF( sub(L_frame, L_FRAME) == 0)
{
FOR (j=0; j<128; j++)
{
L_tmp = L_mult0(*pt_fft_io, *pt_fft_io);
pt_fft_io++;
L_tmp = L_mac0(L_tmp, *pt_fft_io, *pt_fft_io); /* 2*(Q_exc) */
pt_fft_io++;
enr1 = L_add(enr1, L_shr(L_tmp, 7)); /* 2*(Q_exc)+1, divide by L_frame done here */
}
}
ELSE /* L_FRAME16k */
{
FOR (j=0; j<160; j++)
{
L_tmp = L_mult0(*pt_fft_io, *pt_fft_io);
pt_fft_io++;
L_tmp = L_mac0(L_tmp, *pt_fft_io, *pt_fft_io); /* 2*(Q_exc) */
pt_fft_io++;
enr1 = L_add(enr1, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_exc)+15+1-16+1, divide by L_frame done here */
}
}
enr1 = L_shr(enr1,sub(add(Q_exc,Q_exc),5));/*Q6*/
/* add time domain randomization */
FOR ( i_subfr=0; i_subfr<L_frame; i_subfr += L_SUBFR )
{
L_tmp = Mult_32_16(enr1, Random(cng_ener_seed1));
L_tmp = Mult_32_16(L_tmp, GAIN_VAR);
L_tmp = L_add(L_tmp, enr1);
L_tmp = L_max(L_tmp, 1);
/* enr = dot_product( fft_io, fft_io, L_SUBFR ) + 0.01f */
tmp = extract_h(Dot_product12(&fft_io[i_subfr], &fft_io[i_subfr], L_SUBFR, &exp));
exp = add(exp, sub(-6, add(Q_exc, Q_exc))); /* -2*Q_exc from fft_io, -6 from L_SUBFR */
/* enr = (float)sqrt( ener_lp*L_SUBFR / enr ) */
exp2 = norm_l(L_tmp);
tmp2 = extract_h(L_shl(L_tmp, exp2));
exp2 = sub(31-6, exp2); /* in Q15 (L_tmp in Q6)*/
exp = sub(exp, exp2);
if (sub(tmp, tmp2) > 0)
{
exp = add(exp, 1);
}
if (sub(tmp, tmp2) > 0)
{
tmp = shr(tmp, 1);
}
tmp = div_s(tmp, tmp2);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp);/*Q(31-exp)*/
test();
test();
test();
IF( L_sub(last_core_brate,SID_2k40) != 0 && L_sub(last_core_brate,SID_1k75) != 0 && L_sub(last_core_brate,FRAME_NO_DATA) != 0 && L_sub(core_brate,SID_2k40) == 0 )
{
IF ( L_sub(L_tmp,L_shl(1,sub(31,exp))) > 0 )
{
L_tmp = L_shl(1,sub(31,exp));
}
}
tmp = extract_h(L_tmp);
FOR (i=0; i<L_SUBFR; i++)
{
/* fft_io[i] *= enr */
L_tmp = L_mult(fft_io[i_subfr+i], tmp); /* Q_exc + 16 - exp */
fft_io[i_subfr+i] = round_fx(L_shl(L_tmp, exp));/*Q_exc*/
}
}
FOR ( i=0; i<L_frame; i++ )
{
/* fft_io[i] = 0.75f*fft_io[i] + exc2[i];*/
tmp = mult(fft_io[i],24576);
fft_io[i] = add(tmp,exc2[i]);
move16();/*Q_exc*/
}
/* enr = (dotp( fft_io, fft_io, L_frame ) / L_frame) + 0.01f */
L_tmp2 = L_deposit_l(1);
pt_fft_io = fft_io;
IF( sub(L_frame, L_FRAME) == 0)
{
FOR (j=0; j<128; j++)
{
L_tmp = L_mult0(*pt_fft_io, *pt_fft_io);
pt_fft_io++;
L_tmp = L_mac0(L_tmp, *pt_fft_io, *pt_fft_io); /* 2*(Q_exc) */
pt_fft_io++;
L_tmp2 = L_add(L_tmp2, L_shr(L_tmp, 7)); /* 2*(Q_exc)+1, divide by L_frame done here */
}
}
ELSE /* L_FRAME16k */
{
FOR (j=0; j<160; j++)
{
L_tmp = L_mult0(*pt_fft_io, *pt_fft_io);
pt_fft_io++;
L_tmp = L_mac0(L_tmp, *pt_fft_io, *pt_fft_io); /* 2*(Q_exc) */
pt_fft_io++;
L_tmp2 = L_add(L_tmp2, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_exc)+15+1-16+1, divide by L_frame done here */
}
}
L_tmp2 = L_shr(L_tmp2,sub(add(Q_exc,Q_exc),5));/*Q6*/
/* enr = (*lp_ener)/enr; */
/* ftmp = sqrt(enr); */
L_tmp = L_max(1, *lp_ener); /*Q6*/
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
exp = sub(31-6, exp); /* in Q15 (L_tmp in Q6)*/
exp2 = norm_l(L_tmp2);
tmp2 = extract_h(L_shl(L_tmp2, exp2));
exp2 = sub(31-6, exp2); /* in Q15 (L_tmp in Q6)*/
exp = sub(exp2, exp); /* Denormalize and substract */
if (sub(tmp2, tmp) > 0)
{
exp = add(exp, 1);
}
if (sub(tmp2, tmp) > 0)
{
tmp2 = shr(tmp2, 1);
}
tmp = div_s(tmp2, tmp);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp)*/
ftmp = extract_h(L_shl(L_tmp,exp));/* Q15 */
FOR (i=0; i<L_frame; i++)
{
/* fft_io[i] *= ftmp;*/
fft_io[i] = mult(fft_io[i],ftmp);
move16();/* Q_exc */
}
Copy( fft_io, exc2, L_frame );
}
IF ( sub(Opt_AMR_WB,1) != 0 )
{
Copy( exc3, exc, L_frame );
}
ELSE
{
Copy( exc2, exc, L_frame );
}
IF( sub(L_frame,L_FRAME) == 0)
{
interp_code_5over2_fx( exc2, bwe_exc, L_FRAME );
}
ELSE
{
interp_code_4over2_fx( exc2, bwe_exc, L_frame );
}
return;
}
/*-------------------------------------------------------*
* cng_params_postupd_fx
*
* Post-update of CNG parameters
*-------------------------------------------------------*/
void cng_params_postupd_fx(
const Word16 ho_circ_ptr, /* i : pointer for CNG averaging buffers Q0 */
Word16 *cng_buf_cnt, /* i/o: counter for CNG store buffers Q0 */
const Word16 *const cng_exc2_buf, /* i : Excitation buffer Q_exc */
const Word16 *const cng_Qexc_buf, /* i : Q_exc buffer Q0 */
const Word32 *const cng_brate_buf, /* i : bit rate buffer Q0 */
Word32 ho_env_circ[] /* i/o: Envelope buffer */
)
{
Word16 i, j;
Word16 Q_exc;
const Word16 *exc2;
Word16 fft_io[L_FFT];
Word32 sp[129];
Word16 *ptR,*ptI;
Word32 env[NUM_ENV_CNG];
Word32 L_tmp;
Word16 tmp;
Word16 temp_lo_fx, temp_hi_fx;
Word16 exp_pow;
Word16 exp1;
Word16 CNG_mode;
Word16 ptr;
Word32 last_active_brate;
ptr = add( sub(ho_circ_ptr, *cng_buf_cnt), 1);
if( ptr < 0 )
{
ptr = add(ptr, HO_HIST_SIZE);
}
FOR( j = 0; j < *cng_buf_cnt; j++ )
{
exc2 = &cng_exc2_buf[ptr*L_FFT];
Q_exc = cng_Qexc_buf[ptr];
last_active_brate = cng_brate_buf[ptr];
/* calculate the spectrum of residual signal */
Copy(exc2, fft_io, L_FFT);
fft_rel_fx(fft_io, L_FFT, LOG2_L_FFT);
ptR = &fft_io[1];
ptI = &fft_io[L_FFT-1];
FOR (i=0; i<NUM_ENV_CNG; i++)
{
/* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
L_tmp = L_mult(*ptR,*ptR);/* 2*Q_exc+1 */
L_tmp = L_add(L_tmp,L_mult(*ptI,*ptI));/* 2*Q_exc+1 */
L_tmp = L_add(L_tmp,L_tmp);/* 2*Q_exc+1 */
L_tmp = Mult_32_16(L_tmp,128);/* 2*Q_exc+1 */
tmp = add(add(Q_exc,Q_exc),1);
sp[i] = L_shr(L_tmp,sub(tmp,6));
move32();/* Q6 */
ptR++;
ptI--;
}
Copy32(sp,env,NUM_ENV_CNG);
IF( L_sub(last_active_brate,ACELP_13k20) > 0 )
{
CNG_mode = 4;
}
ELSE IF( L_sub(last_active_brate,ACELP_9k60) > 0 )
{
CNG_mode = 3;
}
ELSE IF( L_sub(last_active_brate,ACELP_8k00) > 0 )
{
CNG_mode = 2;
}
ELSE IF( L_sub(last_active_brate,ACELP_7k20) > 0 )
{
CNG_mode = 1;
}
ELSE
{
CNG_mode = 0;
}
/* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
L_tmp = L_shl(L_deposit_l(ENR_ATT_fx[CNG_mode]), 8);/* 16 */
temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx);
exp_pow = sub(14, temp_hi_fx);
L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */
L_tmp = L_shl(L_tmp, sub(13, exp_pow)); /* Q13 */
tmp = extract_l(L_tmp);/* Q13 */
exp1 = norm_s(tmp);
tmp = shl(tmp, exp1);/*Q(exp1+13) */
tmp = div_s(16384,tmp); /*Q(15+14-exp1-13) */
tmp = shr(tmp,sub(1,exp1));/* Q15 */
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
env[i] = Mult_32_16(env[i],tmp);
move32();
}
/* update the circular buffer of old residual envelope */
Copy32( env, &(ho_env_circ[(ptr)*NUM_ENV_CNG]), NUM_ENV_CNG );
ptr = add(ptr, 1);
if(sub(ptr, HO_HIST_SIZE) == 0)
{
ptr = 0;
}
}
*cng_buf_cnt = 0;
return;
}
/*-------------------------------------------------------*
* cng_params_upd_fx()
*
* update CNG parameters
*-------------------------------------------------------*/
void cng_params_upd_fx(
const Word16 lsp_new[], /* i : LSP aprameters Q15 */
const Word16 exc2[], /* i : current enhanced excitation Q_exc */
const Word16 L_frame, /* i : frame length Q0 */
Word16 *ho_circ_ptr, /* i/o: pointer for CNG averaging buffers Q0 */
Word32 ho_ener_circ[], /* o : energy buffer for CNG averaging Q6 */
Word16 *ho_circ_size, /* i/o: size of DTX hangover history buffer for averaging Q0 */
Word16 ho_lsp_circ[], /* o : old LSP buffer for CNG averaging Q15 */
const Word16 Q_exc, /* i : Q value of excitation */
const Word16 enc_dec_flag, /* i : Flag indicating encoder or decoder (ENC,DEC) */
Word32 ho_env_circ[], /* i/o: Envelope buffer */
Word16 *cng_buf_cnt, /* i/o: Counter of postponed FFT-processing instances */
Word16 cng_exc2_buf[], /* i/o: Excitation buffer Q_exc */
Word16 cng_Qexc_buf[], /* i/o: Q_exc buffer Q0 */
Word32 cng_brate_buf[], /* i/o: last_active_brate buffer Q0 */
const Word32 last_active_brate /* i : Last active bit rate Q0 */
)
{
Word32 L_ener, L_tmp;
Word16 i, j;
const Word16 *pt_exc2;
Word16 tmpv, maxv, scale;
Word16 fft_io[L_FRAME16k];
Word32 sp[129];
Word16 *ptR,*ptI;
Word32 env[NUM_ENV_CNG];
Word16 exp1;
Word16 CNG_mode;
Word16 tmp;
Word16 temp_lo_fx, temp_hi_fx;
Word16 exp_pow;
/* update the pointer to circular buffer of old LSP vectors */
*ho_circ_ptr = add(*ho_circ_ptr,1);
if( sub(*ho_circ_ptr, HO_HIST_SIZE) == 0 )
{
*ho_circ_ptr = 0;
move16();
}
/* update the circular buffer of old LSP vectors with the new LSP vector */
Copy( lsp_new, &(ho_lsp_circ[(*ho_circ_ptr)*M]), M );
/* calculate the residual signal energy */
/*enr = dotp( exc2, exc2, L_frame ) / L_frame; */
maxv = 0;
move16();
FOR(i = 0; i < L_frame; i++)
{
maxv = s_max(maxv, abs_s(exc2[i]));
}
scale = norm_s(maxv);
pt_exc2 = exc2;
move16();
L_ener = L_deposit_l(0);
IF( sub(L_frame, L_FRAME) == 0)
{
FOR (j=0; j<128; j++)
{
tmpv = shl(*pt_exc2,scale);
L_tmp = L_mult0(tmpv, tmpv); /* 2*(Q_exc+scale) */
pt_exc2++;
tmpv = shl(*pt_exc2,scale);
L_tmp = L_mac0(L_tmp, tmpv, tmpv);
pt_exc2++;
L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* Q(2*(Q_exc+scale)+1) ,division by L_frame done here */
}
}
ELSE /* L_FRAME16k */
{
FOR (j=0; j<160; j++)
{
tmpv = shl(*pt_exc2,scale);
L_tmp = L_mult0(tmpv, tmpv); /* 2*(Q_exc+scale) */
pt_exc2++;
tmpv = shl(*pt_exc2,scale);
L_tmp = L_mac0(L_tmp, tmpv, tmpv);
pt_exc2++;
L_ener = L_add(L_ener, L_shr( Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* Q(2*(Q_exc+scale)+15+1-16+1) ,division by L_frame done here */
}
}
L_ener = L_shr(L_ener, sub(shl(add(Q_exc,scale),1),5)); /* Q6 (2*(Q_exc+scale)+1-2*(Q_exc+scale)+5) */
/* update the circular buffer of old energies */
ho_ener_circ[*ho_circ_ptr] = L_ener;
move32();
IF( sub(enc_dec_flag, ENC) == 0 )
{
/* Store residual signal for postponed FFT-processing*/
*cng_buf_cnt = add(*cng_buf_cnt,1);
if( sub(*cng_buf_cnt, HO_HIST_SIZE) > 0 )
{
*cng_buf_cnt = HO_HIST_SIZE;
move16();
}
Copy( exc2, &(cng_exc2_buf[(*ho_circ_ptr)*L_FFT]), L_FFT );
cng_Qexc_buf[*ho_circ_ptr] = Q_exc;
move16();
cng_brate_buf[*ho_circ_ptr] = last_active_brate;
move16();
}
ELSE
{
/* calculate the spectrum of residual signal */
Copy(exc2, fft_io, L_frame);
fft_rel_fx(fft_io, L_FFT, LOG2_L_FFT);
ptR = &fft_io[1];
ptI = &fft_io[L_FFT-1];
FOR (i=0; i<NUM_ENV_CNG; i++)
{
/* sp[i] = 2.0f*(*ptR * *ptR + *ptI * *ptI)/L_FFT; */
L_tmp = L_mult(*ptR,*ptR);/* 2*Q_exc+1 */
L_tmp = L_add(L_tmp,L_mult(*ptI,*ptI));/* 2*Q_exc+1 */
L_tmp = L_add(L_tmp,L_tmp);/* 2*Q_exc+1 */
L_tmp = Mult_32_16(L_tmp,128);/* 2*Q_exc+1 */
tmp = add(add(Q_exc,Q_exc),1);
sp[i] = L_shr(L_tmp,sub(tmp,6));
move32();/* Q6 */
ptR++;
ptI--;
}
Copy32(sp,env,NUM_ENV_CNG);
IF( L_sub(last_active_brate,ACELP_13k20) > 0 )
{
CNG_mode = 4;
}
ELSE IF( L_sub(last_active_brate,ACELP_9k60) > 0 )
{
CNG_mode = 3;
}
ELSE IF( L_sub(last_active_brate,ACELP_8k00) > 0 )
{
CNG_mode = 2;
}
ELSE IF( L_sub(last_active_brate,ACELP_7k20) > 0 )
{
CNG_mode = 1;
}
ELSE
{
CNG_mode = 0;
}
/* att = 1/pow(2,ENR_ATT_fx[CNG_mode]); */
L_tmp = L_shl(L_deposit_l(ENR_ATT_fx[CNG_mode]), 8);/* 16 */
temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx);
exp_pow = sub(14, temp_hi_fx);
L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */
L_tmp = L_shl(L_tmp, sub(13, exp_pow)); /* Q13 */
tmp = extract_l(L_tmp);/* Q13 */
exp1 = norm_s(tmp);
tmp = shl(tmp, exp1);/*Q(exp1+13) */
tmp = div_s(16384,tmp); /*Q(15+14-exp1-13) */
tmp = shr(tmp,sub(1,exp1));/* Q15 */
FOR ( i=0; i<NUM_ENV_CNG; i++ )
{
env[i] = Mult_32_16(env[i],tmp);
move32();
}
/* update the circular buffer of old residual envelope */
/* Copy32( env, &(ho_env_circ[add(shl(*ho_circ_ptr,4),shl(*ho_circ_ptr,2))]), NUM_ENV_CNG ); */
Copy32( env, &(ho_env_circ[(*ho_circ_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG );
}
*ho_circ_size = add(*ho_circ_size,1);
if( sub(*ho_circ_size,HO_HIST_SIZE) > 0 )
{
*ho_circ_size = HO_HIST_SIZE;
move16();
}
return;
}
+2371
View File
File diff suppressed because it is too large Load Diff
+288
View File
@@ -0,0 +1,288 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "prot_fx.h"
#include "options.h"
#include "stl.h"
#include "prot_fx.h"
#include "basop_util.h"
#include "rom_basop_util.h"
#define inv_int InvIntTable
Word16 tcxGetNoiseFillingTilt(Word16 A[], Word16 lpcorder, Word16 L_frame, Word16 mode, Word16 *noiseTiltFactor)
{
Word16 firstLine;
Word32 tmp;
Word16 As[M+1];
IF (mode != 0)
{
firstLine = idiv1616U(L_frame, 6);
*noiseTiltFactor = 18432/*0.5625f Q15*/;
move16();
}
ELSE
{
firstLine = shr(L_frame, 3);
Copy_Scale_sig( A, As, lpcorder+1, sub(norm_s(A[0]),2) );
tmp = get_gain(As+1, As, lpcorder);
BASOP_SATURATE_WARNING_OFF;
*noiseTiltFactor = add(round_fx(L_shl(tmp, 15)), 3072/*0.09375f Q15*/);
move16();
BASOP_SATURATE_WARNING_ON;
}
return firstLine;
}
void tcxFormantEnhancement(
Word16 xn_buf[],
Word16 gainlpc[], Word16 gainlpc_e[],
Word32 spectrum[], Word16 *spectrum_e,
Word16 L_frame,
Word16 L_frameTCX
)
{
Word16 i, j, k, l, n;
Word16 fac, fac0, fac1, fac_e, d, tmp;
Word16 xn_buf_e, xn_one, m, e;
k = shr(L_frame, 6); /* FDNS_NPTS = 64 */
l = 0;
move16();
/* get exponent */
xn_buf_e = 0;
move16();
FOR (i = 0; i < FDNS_NPTS; i++)
{
xn_buf_e = s_max(xn_buf_e, gainlpc_e[i]);
}
xn_buf_e = shr(add(xn_buf_e, 1), 1); /* max exponent after sqrt */
xn_one = shr(0x4000, sub(xn_buf_e, 1)); /* 1.0 scaled to xn_buf_e */
/* Formant enhancement via square root of the LPC gains */
e = gainlpc_e[0];
move16();
m = Sqrt16(gainlpc[0], &e);
xn_buf[0] = shl(m, sub(e, xn_buf_e));
move16();
e = gainlpc_e[1];
move16();
m = Sqrt16(gainlpc[1], &e);
xn_buf[1] = shl(m, sub(e, xn_buf_e));
move16();
fac0 = s_min(xn_buf[0], xn_buf[1]);
fac_e = xn_buf_e;
move16();
fac0 = Inv16(fac0, &fac_e);
FOR (i = 1; i < FDNS_NPTS-1; i++)
{
e = gainlpc_e[i+1];
move16();
m = Sqrt16(gainlpc[i+1], &e);
xn_buf[i+1] = shl(m, sub(e, xn_buf_e));
move16();
test();
IF ((sub(xn_buf[i-1], xn_buf[i]) <= 0) && (sub(xn_buf[i+1], xn_buf[i]) <= 0))
{
m = s_max(xn_buf[i-1], xn_buf[i+1]);
e = xn_buf_e;
move16();
m = Inv16(m, &e);
fac1 = m;
move16();
tmp = sub(e, fac_e);
if (tmp > 0) fac0 = shr(fac0, tmp);
if (tmp < 0) fac1 = shl(fac1, tmp);
if (tmp > 0)
{
fac_e = e;
move16();
}
d = sub(fac1, fac0);
n = sub(i, l);
assert(n <= 64);
xn_buf[l] = xn_one;
move16();
FOR (j = 1; j < n; j++)
{
fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n]))));
BASOP_SATURATE_WARNING_OFF;
xn_buf[l+j] = s_min(xn_one, shl(mult(xn_buf[l+j], fac), fac_e));
move16();
BASOP_SATURATE_WARNING_ON;
}
l = i;
move16();
fac0 = m;
move16();
fac_e = e;
move16();
}
}
/* i = FDNS_NPTS - 1; Completing changes to gains */
m = s_min(xn_buf[i-1], xn_buf[i]);
e = xn_buf_e;
move16();
m = Inv16(m, &e);
fac1 = m;
move16();
tmp = sub(e, fac_e);
if (tmp > 0) fac0 = shr(fac0, tmp);
if (tmp < 0) fac1 = shl(fac1, tmp);
if (tmp > 0)
{
fac_e = e;
move16();
}
d = sub(fac1, fac0);
n = sub(i, l);
assert(n <= 64);
xn_buf[l] = xn_one;
move16();
FOR (j = 1; j < n; j++)
{
fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n]))));
BASOP_SATURATE_WARNING_OFF;
xn_buf[l+j] = s_min(xn_one, shl(mult(xn_buf[l+j], fac), fac_e));
move16();
BASOP_SATURATE_WARNING_ON;
}
xn_buf[i] = xn_one;
move16();
/* Application of changed gains onto decoded MDCT lines */
FOR (i = 0; i < L_frame; i += k)
{
FOR (l = 0; l < k; l++)
{
*spectrum = Mpy_32_16_1(*spectrum, *xn_buf);
move32();
spectrum++;
}
xn_buf++;
}
tmp = sub(L_frameTCX, L_frame);
FOR (i = 0; i < tmp; i++)
{
spectrum[i] = L_shr(spectrum[i], xn_buf_e);
move32();
}
*spectrum_e = add(*spectrum_e, xn_buf_e);
move16();
}
void tcxInvertWindowGrouping(TCX_config *tcx_cfg,
Word32 xn_buf[],
Word32 spectrum[],
Word16 L_frame,
Word8 fUseTns,
Word16 last_core,
Word16 index,
Word16 frame_cnt,
Word16 bfi)
{
Word16 i, L_win, L_spec;
Word32 *p;
L_win = shr(L_frame, 1);
L_spec = tcx_cfg->tnsConfig[0][0].iFilterBorders[0];
move16();
test();
test();
if ((frame_cnt != 0) && (bfi == 0) && (last_core != ACELP_CORE)) /* fix sub-window overlap */
{
tcx_cfg->tcx_last_overlap_mode = tcx_cfg->tcx_curr_overlap_mode;
move16();
}
test();
test();
test();
test();
test();
test();
test();
IF (((bfi==0) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) ||
((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0))))
||
((bfi!=0) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) &&
!(tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP))))
{
/* ungroup sub-windows: deinterleave MDCT bins into separate windows */
p = xn_buf;
FOR (i = 1; i < L_win; i += 2)
{
*p++ = spectrum[i];
move32();
}
p = spectrum;
FOR (i = 0; i < L_frame; i += 2)
{
*p++ = spectrum[i];
move32();
}
p = spectrum + L_frame - 1;
FOR (i = sub(L_frame, 1); i > L_win; i -= 2)
{
*p-- = spectrum[i];
move32();
}
Copy32(xn_buf, spectrum + L_win, shr(L_win, 1));
test();
test();
IF ((tcx_cfg->fIsTNSAllowed != 0) && (bfi == 0) && (fUseTns != 0))
{
/* rearrange LF sub-window lines prior to TNS synthesis filtering */
IF (sub(L_spec, L_frame) < 0)
{
Copy32(spectrum+8, spectrum+16, sub(shr(L_spec,1),8));
Copy32(spectrum+L_frame/2, spectrum+8, 8);
Copy32(spectrum+L_frame/2+8, spectrum+L_spec/2+8, sub(shr(L_spec,1),8));
}
ELSE
{
Copy32(spectrum+L_win, xn_buf, 8);
Copy32(spectrum+8, spectrum+16, sub(L_win, 8));
Copy32(xn_buf, spectrum+8, 8);
}
}
}
}
+471
View File
@@ -0,0 +1,471 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "options.h"
#include "stl.h"
#include "basop_util.h"
#include "prot_fx.h"
#include "rom_com_fx.h"
Word8 getTcxonly(const Word32 bitrate)
{
Word8 tcxonly;
tcxonly = 0;
move16();
if( L_sub(bitrate,32000) > 0 )
{
tcxonly = 1;
move16();
}
return tcxonly;
}
Word8 getCtxHm(const Word32 bitrate, const Word16 rf_flag)
{
Word8 ctx_hm;
ctx_hm = 0;
move16();
test();
if( (bitrate > LPC_SHAPED_ARI_MAX_RATE) && (bitrate <= 64000) && !rf_flag)
{
ctx_hm = 1;
move16();
}
return ctx_hm;
}
Word8 getResq(const Word32 bitrate)
{
Word8 resq;
resq = 0;
move16();
if (L_sub(bitrate,64000) <= 0)
{
resq = 1;
move16();
}
return resq;
}
Word8 getTnsAllowed(const Word32 bitrate
,const Word16 igf
)
{
Word8 tnsAllowed;
tnsAllowed = 0;
move16();
IF ( igf != 0 )
{
if( L_sub(bitrate, HQ_16k40) > 0 )
{
tnsAllowed = 1;
move16();
}
}
ELSE
{
if( L_sub(bitrate, HQ_32k) > 0)
{
tnsAllowed = 1;
move16();
}
}
return tnsAllowed;
}
Word8 getRestrictedMode(const Word32 bitrate, const Word16 Opt_AMR_WB)
{
Word8 restrictedMode;
restrictedMode = 3;
move16();
test();
IF ( (Opt_AMR_WB == 0) && (L_sub(bitrate,32000) > 0 ) )
{
restrictedMode = 6;
move16();
}
ELSE IF( Opt_AMR_WB )
{
restrictedMode = 1;
move16();
}
return restrictedMode;
}
Word16 sr2fscale(const Word32 sr)
{
Word16 fscale;
SWITCH(sr)
{
case 8000:
fscale = (FSCALE_DENOM*8000)/12800;
move16();
BREAK;
case 12800:
fscale = FSCALE_DENOM;
move16();
BREAK;
case 16000:
fscale = (FSCALE_DENOM*16000)/12800;
move16();
BREAK;
case 25600:
fscale = (FSCALE_DENOM*25600)/12800;
move16();
BREAK;
case 32000:
fscale = (FSCALE_DENOM*32000)/12800;
move16();
BREAK;
case 48000:
fscale = (FSCALE_DENOM*48000)/12800;
move16();
BREAK;
default:
assert(0);
fscale = 0; /* just to avoid compiler warning */
BREAK;
}
return fscale;
}
Word32 getCoreSamplerateMode2(const Word32 bitrate, const Word16 bandwidth, const Word16 rf_mode)
{
Word32 sr_core;
sr_core = -1; /* to suppress MSVC warning */ move32();
test();
test();
test();
test();
test();
test();
test();
test();
IF( L_sub( bandwidth,NB) == 0 )
{
sr_core = 12800;
move32();
}
ELSE IF ( L_and(L_sub(bandwidth,WB)==0, L_sub(bitrate,13200)<0) ||
L_and(L_sub(bandwidth,SWB)==0, L_sub(bitrate,13200)<=0) || sub(rf_mode,1) == 0 )
{
sr_core = 12800;
move32();
}
ELSE IF (L_sub(bandwidth,WB)==0 || ( (L_sub(bitrate,32000)<=0) && ((L_sub(bandwidth,SWB)==0) || (L_sub(bandwidth,FB)==0)) ) )
{
sr_core = 16000;
move32();
}
ELSE IF ( ((L_sub(bandwidth,SWB)==0) || (L_sub(bandwidth,FB)==0)) && (L_sub(bitrate,64000)<=0) )
{
sr_core = 25600;
move32();
}
ELSE IF (L_sub(bandwidth,SWB)==0 || L_sub(bandwidth,FB)==0)
{
sr_core = 32000;
move32();
}
ELSE
{
assert(0);
}
return sr_core;
}
Word16 getTcxBandwidth(const Word16 bandwidth)
{
Word16 tcxBandwidth;
tcxBandwidth = 16384/*0.5f Q15*/;
move16();
if(sub(bandwidth, NB) == 0)
{
tcxBandwidth = 10240/*0.3125f Q15*/;
move16();
}
return tcxBandwidth;
}
Word8 getIgfPresent(
const Word32 bitrate,
const Word16 bandwidth
,const Word16 rf_mode
)
{
Word8 igfPresent;
igfPresent = 0;
move16();
test();
test();
if( (sub(bandwidth, SWB) == 0) && (L_sub(bitrate, ACELP_9k60) >= 0) && (L_sub(bitrate, HQ_96k) < 0) )
{
igfPresent = 1;
move16();
}
test();
if( sub(bandwidth, FB) == 0 && (L_sub(bitrate, ACELP_16k40) >= 0))
{
igfPresent = 1;
move16();
}
test();
if( (sub(bandwidth, WB) == 0) && (L_sub(bitrate, ACELP_9k60) == 0) )
{
igfPresent = 1;
move16();
}
test();
test();
test();
if( ((sub(bandwidth, WB) == 0) || (sub(bandwidth, SWB) == 0)) && (sub(rf_mode, 1) == 0) && (L_sub(bitrate, ACELP_13k20) == 0) )
{
igfPresent = 1;
move16();
}
return igfPresent;
}
Word8 getCnaPresent(
const Word32 bitrate,
const Word16 bandwidth
)
{
Word8 flag_cna = 0;
flag_cna = 0;
move16();
test();
if( sub(bandwidth, NB) == 0 && (L_sub(bitrate, ACELP_13k20) <= 0) )
{
flag_cna = 1;
move16();
}
test();
if( (sub(bandwidth, WB) == 0) && (L_sub(bitrate, ACELP_13k20) <= 0) )
{
flag_cna = 1;
move16();
}
test();
if( (sub(bandwidth, SWB) == 0) && (L_sub(bitrate, ACELP_13k20) <= 0) )
{
flag_cna = 1;
move16();
}
return flag_cna;
}
Word8 getTcxLtp(const Word32 sr_core)
{
Word8 tcxltp = 0;
tcxltp = 0;
move16();
test();
if ( (L_sub(sr_core, 25600) <= 0) )
{
tcxltp = 1;
move16();
}
return tcxltp;
}
Word16 initPitchLagParameters(
const Word32 sr_core,
Word16 *pit_min,
Word16 *pit_fr1,
Word16 *pit_fr1b,
Word16 *pit_fr2,
Word16 *pit_max
)
{
Word16 pit_res_max;
IF (L_sub(sr_core, 12800) == 0)
{
*pit_min = PIT_MIN_12k8;
move16();
*pit_max = PIT_MAX_12k8;
move16();
*pit_fr2 = PIT_FR2_12k8;
move16();
*pit_fr1 = PIT_FR1_12k8;
move16();
*pit_fr1b = PIT_FR1_8b_12k8;
move16();
pit_res_max = 4;
move16();
}
ELSE IF (L_sub(sr_core, 16000) == 0)
{
*pit_min = PIT_MIN_16k;
move16();
*pit_max = PIT_MAX_16k;
move16();
*pit_fr2 = PIT_FR2_16k;
move16();
*pit_fr1 = PIT_FR1_16k;
move16();
*pit_fr1b = PIT_FR1_8b_16k;
move16();
pit_res_max = 6;
move16();
}
ELSE IF (L_sub(sr_core, 25600) == 0)
{
*pit_min = PIT_MIN_25k6;
move16();
*pit_max = PIT_MAX_25k6;
move16();
*pit_fr2 = PIT_FR2_25k6;
move16();
*pit_fr1 = PIT_FR1_25k6;
move16();
*pit_fr1b = PIT_FR1_8b_25k6;
move16();
pit_res_max = 4;
move16();
}
ELSE /* sr_core==32000 */
{
*pit_min = PIT_MIN_32k;
move16();
*pit_max = PIT_MAX_32k;
move16();
*pit_fr2 = PIT_FR2_32k;
move16();
*pit_fr1 = PIT_FR1_32k;
move16();
*pit_fr1b = PIT_FR1_8b_32k;
move16();
pit_res_max = 6;
move16();
}
return pit_res_max;
}
Word16 getNumTcxCodedLines(const Word16 bwidth)
{
Word16 tcx_coded_lines;
tcx_coded_lines = 0;
move16();
if(sub(bwidth, NB) == 0)
{
tcx_coded_lines = 160;
move16();
}
if(sub(bwidth, WB) == 0)
{
tcx_coded_lines = 320;
move16();
}
if(sub(bwidth, SWB) == 0)
{
tcx_coded_lines = 640;
move16();
}
if(sub(bwidth, FB) == 0)
{
tcx_coded_lines = 960;
move16();
}
return tcx_coded_lines;
}
Word16 getTcxLpcShapedAri(
const Word32 total_brate,
const Word16 bwidth
,const Word16 rf_mode
)
{
Word16 tcx_lpc_shaped_ari = 0;
move16();
(void) bwidth;
test();
if( (L_sub(total_brate, LPC_SHAPED_ARI_MAX_RATE) <= 0) || rf_mode )
{
tcx_lpc_shaped_ari = 1;
move16();
}
return tcx_lpc_shaped_ari;
}
+136
View File
@@ -0,0 +1,136 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#include "basop_util.h"
/*========================================================================*/
/* FUNCTION : deemph_fx() */
/*------------------------------------------------------------------------*/
/* PURPOSE : Deemphasis: filtering through 1/(1-mu z^-1) */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) mu : deemphasis factor Q15 */
/* _ (Word16) L : vector size */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16*) signal : signal Q_syn2-1 */
/* _ (Word16*) mem : memory (y[-1]) Q_syn2-1 */
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
void deemph_fx(
Word16 *signal, /* i/o: signal Qx */
const Word16 mu, /* i : deemphasis factor Q15 */
const Word16 L, /* i : vector size Q0 */
Word16 *mem /* i/o: memory (y[-1]) Qx */
)
{
Word16 i;
Word32 L_tmp;
L_tmp = L_deposit_h(signal[0]);
L_tmp = L_mac(L_tmp, *mem, mu);
signal[0] = round_fx(L_tmp);
FOR (i = 1; i < L; i++)
{
L_tmp = L_deposit_h(signal[i]);
L_tmp = L_mac(L_tmp, signal[i - 1], mu);
signal[i] = round_fx(L_tmp);
}
*mem = signal[L - 1];
move16();
}
/*-------------------------------------------------------------------*
* Deeemph2 :
*
* Deemphasis: filtering through 1/(1-mu z^-1)
* Output divided by 2
*-------------------------------------------------------------------*/
void Deemph2(
Word16 x[], /* i/o: input signal overwritten by the output Qx/Qx-1 */
const Word16 mu, /* i : deemphasis factor Q15 */
const Word16 L, /* i : vector size Q0 */
Word16 *mem /* i/o: memory (y[-1]) Qx-1 */
)
{
Word16 i;
Word32 L_tmp;
/* saturation can occur in L_mac() */
L_tmp = L_mult(x[0], 16384);
x[0] = mac_r(L_tmp, *mem, mu);
move16();
FOR (i = 1; i < L; i++)
{
L_tmp = L_mult(x[i], 16384);
x[i] = mac_r(L_tmp, x[i - 1], mu);
move16();
}
*mem = x[L - 1];
move16();
}
/*
* E_UTIL_deemph2
*
* Parameters:
* shift I: scale output
* x I/O: signal Qx/Qx-shift
* mu I: deemphasis factor Qx
* L I: vector size
* mem I/O: memory (signal[-1]) Qx
*
* Function:
* Filtering through 1/(1-mu z^-1)
* Signal is divided by 2.
*
* Returns:
* void
*/
void E_UTIL_deemph2(Word16 shift, Word16 *x, const Word16 mu, const Word16 L, Word16 *mem)
{
Word16 i;
Word32 L_tmp;
/* signal[0] = signal[0] + mu * (*mem); */
L_tmp = L_deposit_h(*mem);
IF(shift >= 0)
{
shift = shr(-32768, shift);
FOR (i = 0; i < L; i++)
{
L_tmp = L_msu(Mpy_32_16_1(L_tmp, mu), x[i],shift);
x[i] = round_fx(L_tmp);
}
}
ELSE
{
FOR (i = 0; i < L; i++)
{
L_tmp = L_msu(Mpy_32_16_1(L_tmp, mu), shr(x[i],shift),-32768);
x[i] = round_fx(L_tmp);
}
}
*mem = x[L - 1];
move16();
return;
}
+43
View File
@@ -0,0 +1,43 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h"
#include "prot_fx.h"
/*--------------------------------------------------------------------------
* get_delay_fx()
*
* Function returns various types of delays in the codec in ms.
*--------------------------------------------------------------------------*/
Word32 get_delay_fx( /* o : delay value in ms */
const Word16 what_delay, /* i : what delay? (ENC or DEC) */
const Word32 io_fs /* i : input/output sampling frequency */
)
{
Word32 delay = 0;
IF( sub(what_delay,ENC) == 0 )
{
delay = (DELAY_FIR_RESAMPL_NS + ACELP_LOOK_NS);
move32();
}
ELSE
{
IF( L_sub(io_fs,8000) == 0 )
{
delay = DELAY_CLDFB_NS;
move32();
}
ELSE
{
delay = DELAY_BWE_TOTAL_NS;
move32();
}
}
return delay;
}
+18
View File
@@ -0,0 +1,18 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "disclaimer.h"
#include "options.h"
#include "stl.h"
/* WMC_TOOL_SKIP_FILE */
int print_disclaimer(FILE *fPtr)
{
fprintf(fPtr, "\n==============================================================================\n");
fprintf(fPtr, " EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0\n");
fprintf(fPtr, "==============================================================================\n\n\n");
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef __INCLUDED_DISCLAIMER_H
#define __INCLUDED_DISCLAIMER_H
#include <stdio.h>
int print_disclaimer(FILE *fPtr);
#endif /* __INCLUDED_DISCLAIMER_H */
+55
View File
@@ -0,0 +1,55 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
/* Header files */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "prot_fx.h"
#include "stl.h"
#include "prot_fx.h"
void dlpc_bfi(
const Word16 L_frame,
Word16 *lsf_q, /* o : quantized LSFs */
const Word16 *lsfold, /* i : past quantized LSF */
const Word16 last_good, /* i : last good received frame */
const Word16 nbLostCmpt, /* i : counter of consecutive bad frames */
Word16 mem_MA[], /* i/o: quantizer memory for MA model */
Word16 mem_AR[], /* i/o: quantizer memory for AR model */
Word16 *stab_fac, /* i : LSF stability factor */
Word16 *lsf_adaptive_mean,/* i : LSF adaptive mean, updated when BFI==0 */
Word16 numlpc, /* i : Number of division per superframe */
Word16 lsf_cng[],
Word8 plcBackgroundNoiseUpdated,
Word16 *lsf_q_cng, /* o : quantized LSFs */
Word16 *old_lsf_q_cng, /* o : old quantized LSFs for background noise */
const Word16* lsfBase, /* i : base for differential LSF coding */
Word8 tcxonly
)
{
lsf_dec_bfi(
MODE2,
&lsf_q[0], lsfold, lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac,
0, L_frame, last_good, nbLostCmpt,
plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, tcxonly
,0
);
IF ( sub(numlpc,2)==0 )
{
/* Decode the second LPC */
lsf_dec_bfi(
MODE2,
&lsf_q[M], &lsf_q[0], lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac,
0, L_frame, last_good, nbLostCmpt+1,
plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, tcxonly
,0
);
}
/**/ /*No local variabvles defined*/
}
+426
View File
@@ -0,0 +1,426 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include <assert.h>
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#include "math_32.h"
static Word16 const * get_edct_table(Word16 length, Word16 *q)
{
Word16 const * edct_table = NULL;
SWITCH (length)
{
case 1200:
edct_table = edct_table_600_fx;
move16();
*q = add(*q, 2);
BREAK;
case 960 :
edct_table = edct_table_480_fx;
move16();
BREAK;
case 640 :
edct_table = edct_table_320_fx;
move16();
BREAK;
case 320 :
edct_table = edct_table_160_fx;
move16();
BREAK;
case 256 :
edct_table = edct_table_128_fx;
move16();
BREAK;
case 240 :
edct_table = edct_table_120_fx;
move16();
BREAK;
case 200 :
edct_table = edct_table_100_fx;
move16();
BREAK;
case 160 :
edct_table = edct_table_80_fx ;
move16();
BREAK;
case 40 :
edct_table = edct_table_20_fx ;
move16();
BREAK;
case 800 :
edct_table = edct_table_400_fx;
move16();
*q = add(*q, 2);
BREAK;
case 512 :
edct_table = edct_table_256_fx;
move16();
BREAK;
case 480 :
edct_table = edct_table_240_fx;
move16();
BREAK;
case 400 :
edct_table = edct_table_200_fx;
move16();
BREAK;
case 128 :
edct_table = edct_table_64_fx ;
move16();
BREAK;
case 80 :
edct_table = edct_table_40_fx ;
move16();
BREAK;
default:
BREAK;
}
return edct_table;
}
/*-------------------------------------------------------------------------*
* FUNCTION : edct_fx()
*
* PURPOSE : DCT transform
*
* INPUT ARGUMENTS :
* _ (Word16) length : length
* _ (Word16*) x : input signal Qx
* _ (Word16*) edct_table_128_fx : edct table Q16
*
* OUTPUT ARGUMENTS :
* _ (Word16[]) y : output transform Qx
*-------------------------------------------------------------------------*/
void edct_fx(
const Word32 *x, /* i : input signal Qq */
Word32 *y, /* o : output transform Qq */
Word16 length, /* i : length */
Word16 *q /* i : Q value of input signal */
)
{
Word16 i;
Word32 re;
Word32 im;
const Word16 *edct_table = 0; /*Q16 */
Word32 re2[L_FRAME48k/2+240];
Word32 im2[L_FRAME48k/2+240];
Word32 L_tmp;
Word16 tmp;
Word16 len1;
edct_table = get_edct_table(length, q);
len1 = shr(length, 1);
/* Twiddling and Pre-rotate */
FOR (i = 0; i < len1; i++)
{
L_tmp = Mult_32_16(x[2*i], edct_table[i]); /*Q(q+1) */
re2[i] = Madd_32_16(L_tmp, x[length-1-2*i], edct_table[len1-1-i]); /*Q(q+1) */ move32();
L_tmp = Mult_32_16(x[length-1-2*i], edct_table[i]); /*Q(q+1) */
im2[i] = Msub_32_16(L_tmp, x[2*i], edct_table[len1-1-i]); /*Q(q+1) */ move32();
}
*q = sub(15, *q);
BASOP_cfft(re2, im2, len1, 1, q, y);
tmp = div_s(1, length); /*Q15 */
tmp = round_fx(L_shl(L_mult(tmp, 19302), 2)); /*Q15 */
FOR (i = 0; i < len1; i++)
{
re = Msub_32_16(re2[i], im2[i], tmp);
im = Madd_32_16(im2[i], re2[i], tmp);
y[2 * i] = L_add(Mult_32_16(re, edct_table[i]), Mult_32_16(im, edct_table[len1 - 1 - i]));
move32();
y[length - 1 - 2 * i] = L_sub(Mult_32_16(re, edct_table[len1 - 1 - i]), Mult_32_16(im, edct_table[i]));
move32();
} /*Q(q-2) */
*q = sub(15+2, *q);
return;
}
/*-------------------------------------------------------------------------*
* FUNCTION : edst_fx()
*
* PURPOSE : DST_IV transform
*
* INPUT ARGUMENTS :
* _ (Word16) length : length
* _ (Word16*) x : input signal Qx
* _ (Word16*) edct_table_128_fx : edct table Q16
*
* OUTPUT ARGUMENTS :
* _ (Word16[]) y : output transform Qx
*-------------------------------------------------------------------------*/
void edst_fx(
const Word32 *x, /* i : input signal Qq */
Word32 *y, /* o : output transform Qq */
Word16 length, /* i : length */
Word16 *q /* i : Q value of input signal */
)
{
Word16 i;
Word32 re;
Word32 im;
const Word16 *edct_table = 0; /*Q16 */
Word32 re2[L_FRAME48k/2+240];
Word32 im2[L_FRAME48k/2+240];
Word32 L_tmp;
Word16 tmp;
Word16 len1;
edct_table = get_edct_table(length, q);
len1 = shr(length, 1);
/* Twiddling and Pre-rotate */
FOR (i = 0; i < len1; i++)
{
L_tmp = Mult_32_16(x[length-1-2*i], edct_table[i]);
re2[i] = Madd_32_16(L_tmp, x[2*i], edct_table[len1-1-i]);
move32();
L_tmp = Mult_32_16(x[2*i], edct_table[i]);
im2[i] = Msub_32_16(L_tmp, x[length-1-2*i], edct_table[len1-1-i]);
move32();
}
*q = sub(15, *q);
BASOP_cfft(re2, im2, len1, 1, q, y);
tmp = div_s(1, length); /*Q15 */
tmp = round_fx(L_shl(L_mult(tmp, 19302), 2)); /*Q15 */
FOR (i = 0; i < len1; i++)
{
re = Msub_32_16(re2[i], im2[i], tmp);
im = Madd_32_16(im2[i], re2[i], tmp);
y[2 * i] = L_add(Mult_32_16(re, edct_table[i]), Mult_32_16(im, edct_table[len1 - 1 - i]));
move32();
y[length - 1 - 2 * i] = L_sub(Mult_32_16(im, edct_table[i]), Mult_32_16(re, edct_table[len1 - 1 - i]));
move32();
} /*Q(q) */
*q = sub(15+2, *q);
return;
}
/*========================================================================*/
/* FUNCTION : edct_fx() */
/*------------------------------------------------------------------------*/
/* PURPOSE : DCT transform */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) length : length */
/* _ (Word16*) x : input signal Qx */
/* _ (Word16*) edct_table_128_fx : edct table Q15 */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16[]) y : output transform Qx */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
void edct_16fx(
const Word16 *x, /* i : input signal Qx */
Word16 *y, /* o : output transform Qx */
Word16 length, /* i : length */
Word16 bh /* bit-headroom */
)
{
Word16 i;
Word16 re[L_FRAME48k/2];
Word16 im[L_FRAME48k/2];
const Word16 *edct_table = 0;
Word16 re2[L_FRAME48k/2];
Word16 im2[L_FRAME48k/2];
Word32 L_tmp, Lacc, Lmax;
Word16 tmp, fact;
Word16 Q_edct;
Word16 Len2, i2;
const Word16 *px, *pt;
Word16 *py;
/*COMPLETE: some eDCT sub function are missing */
IF (sub(length,L_FRAME32k) == 0)
{
edct_table = &edct_table_320_16fx[0];
move16();
}
ELSE IF (sub(length,L_FRAME) == 0)
{
edct_table = &edct_table_128_16fx[0];
move16();
}
ELSE IF (sub(length,L_FRAME16k) == 0)
{
edct_table = &edct_table_160_16fx[0];
move16();
}
ELSE
{
}
/* Twiddling and Pre-rotate */
Lmax = L_deposit_l(0);
Len2 = shr(length,1);
px = x + length - 1;
pt = edct_table + Len2 - 1;
FOR (i = 0; i < Len2; i++)
{
i2 = shl(i,1);
L_tmp = L_mult(x[i2],edct_table[i]);/*Q(Qx+16) */
Lacc = L_mac(L_tmp,*px,*pt);/*Q(Qx+16) */
Lmax = L_max(Lmax, Lacc);
L_tmp = L_mult(*px,edct_table[i]);/*Q(Qx+16) */
Lacc = L_msu(L_tmp,x[i2],*pt);/*Q(Qx+16) */
Lmax = L_max(Lmax, Lacc);
px -= 2;
pt--;
}
tmp = 31;
if( Lmax != 0 )
{
tmp = norm_l(Lmax);
}
Q_edct = sub(tmp,bh); /*creating a bit-headroom */
px = x + length - 1;
pt = edct_table + Len2 - 1;
FOR (i = 0; i < Len2; i++)
{
i2 = shl(i,1);
L_tmp = L_mult(x[i2],edct_table[i]);/*Q(Qx+16) */
Lacc = L_mac(L_tmp,*px,*pt);/*Q(Qx+16) */
re2[i] = round_fx(L_shl(Lacc, Q_edct)); /* Q(Qx+Q_edct) */
L_tmp = L_mult(*px,edct_table[i]);/*Q(Qx+16) */
Lacc = L_msu(L_tmp,x[i2],*pt);/*Q(Qx+16) */
im2[i] = round_fx(L_shl(Lacc, Q_edct)); /* Q(Qx+Q_edct) */
px -= 2;
pt--;
}
IF (sub(length,L_FRAME32k) == 0)
{
DoRTFT320_16fx(re2, im2);
}
ELSE IF (sub(length,L_FRAME )== 0)
{
DoRTFT128_16fx(re2, im2);
}
ELSE IF (sub(length,L_FRAME16k) == 0)
{
DoRTFT160_16fx(re2, im2);
}
ELSE
{
}
tmp = div_s(1,length); /*Q15 */
L_tmp = L_mult(tmp,19302); /*Q29, (3*PI/4) in Q13 */
fact = round_fx(L_shl(L_tmp,2)); /*Q15 */
FOR (i = 0; i < length/2; i++)
{
tmp = mult_r(im2[i],fact); /*Q(Qx+Q_edct) */
re[i] = sub(re2[i],tmp); /*Q(Qx+Q_edct) */ move16();
tmp = mult_r(re2[i],fact); /*Q(Qx+Q_edct) */
im[i] = add(im2[i],tmp); /*Q(Qx+Q_edct) */ move16();
}
/* Post-rotate and obtain the output data */
py = y + length - 1;
pt = edct_table + Len2 - 1;
FOR (i = 0; i < Len2; i++)
{
i2 = shl(i,1);
L_tmp = L_mult(re[i],edct_table[i]);/*Q(Qx+Q_edct+16) */
Lacc = L_mac(L_tmp,im[i],*pt);/*Q(Qx+Q_edct+16) */
y[i2] = round_fx(L_shr(Lacc,Q_edct)); /* Q(Qx) */
L_tmp = L_mult(re[i],edct_table[length/2-1-i]);/*Q(Qx+Q_edct+16) */
Lacc = L_msu(L_tmp,im[i],edct_table[i]);/*Q(Qx+Q_edct+16) */
*py = round_fx(L_shr(Lacc,Q_edct)); /* Q(Qx) */
py -= 2;
pt--;
}
return;
}
/*-----------------------------------------------------------------*
* iedct_short_fx()
*
* Inverse EDCT for short frames
*-----------------------------------------------------------------*/
void iedct_short_fx(
const Word32 *in, /* i : input vector */
Word16 *Q, /* i/o: Q value of input */
Word32 *out, /* o : output vector */
const Word16 segment_length /* i : length */
)
{
Word32 alias[MAX_SEGMENT_LENGTH];
Word16 seg_len_div2, seg_len_div4, seg_len_3mul_div4;
Word16 i;
Word16 qtmp, tmp;
qtmp = *Q;
move16();
tmp = 0;
move16();
seg_len_div2 = shr(segment_length, 1);
seg_len_div4 = shr(segment_length, 2);
seg_len_3mul_div4 = add(seg_len_div2, seg_len_div4);
edct_fx(in, alias, seg_len_div2, Q);
FOR (i = 0; i < seg_len_div2; i++)
{
IF (alias[i] != 0)
{
tmp = 1;
move16();
BREAK;
}
}
if (tmp == 0)
{
*Q = qtmp;
move16();
}
FOR (i = 0; i < seg_len_div4; i++)
{
out[i] = alias[seg_len_div4 + i];
move32();
out[seg_len_div4 + i] = L_negate(alias[seg_len_div2 - 1 - i]);
move32();
out[seg_len_div2 + i] = L_negate(alias[seg_len_div4 - 1 - i]);
move32();
out[seg_len_3mul_div4 + i] = L_negate(alias[i]);
move32();
}
return;
}
+678
View File
@@ -0,0 +1,678 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h"
#include "basop_util.h"
/*---------------------------------------------------------------------*
* Local constants
*---------------------------------------------------------------------*/
#define pitch_0_9 14746 /* 0.9 in Q14 */
#define pitch_0_6 9830 /* 0.6 in Q14 */
#define SIZE 64
#define SIZE2 32
#define NUM_STAGES 5
/*---------------------------------------------------------------------*
* Local functions
*---------------------------------------------------------------------*/
static void phase_dispersion_fx(Word32 gain_code,Word16 gain_pit,Word16 code[],Word16 mode,struct dispMem_fx *dm_fx);
static void agc2_fx(const Word16 *sig_in,Word16 *sig_out,const Word16 l_trm);
/*======================================================================================*/
/* FUNCTION : enhancer_fx() */
/*--------------------------------------------------------------------------------------*/
/* PURPOSE : Enhancement of the excitation signal before synthesis */
/*--------------------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word32) core_brate : decoder bitrate */
/* _ (Word16) Opt_AMR_WB : flag indicating AMR-WB IO mode */
/* _ (Word16) coder_type : coder type */
/* _ (Word16) i_subfr : subframe number */
/* _ (Word16) voice_fac : subframe voicing estimation (Q15) */
/* _ (Word16) stab_fac : LP filter stablility measure (Q15) */
/* _ (Word32) norm_gain_code : normalised innovative cb. gain (Q16) */
/* _ (Word16) gain_inov : gain of the unscaled innovation (Q12) */
/* _ (Word16) gain_pit_fx : Pitch gain (Q14) */
/* _ (Word16) Q_exc : Q of the excitation */
/* _ (Word16) Enc : Encoder = 1; decoder = 0 */
/*--------------------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) voice_factors_fx : TBE voicing factor (Q15) */
/*--------------------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word32*) gc_threshold : gain code threshold (Q16) */
/* _ (Word16*[]) code : innovation (Q12) */
/* _ (Word16*[]) exc2 : adapt. excitation/total exc (Q0) */
/* _ (struct dispMem_fx*) dm_fx : phase dispersion algorithm memory */
/* (a[0]->Q0,a[1]->Q16,a[2-7]->Q14) */
/*--------------------------------------------------------------------------------------*/
/* _ None */
/*--------------------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*======================================================================================*/
void enhancer_fx(
const Word32 core_brate, /* i : decoder bitrate */
const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */
const Word16 coder_type, /* i : coder type */
const Word16 i_subfr, /* i : subframe number */
const Word16 L_frame, /* i : frame size */
const Word16 voice_fac, /* i : subframe voicing estimation Q15 */
const Word16 stab_fac, /* i : LP filter stablility measure Q15 */
Word32 norm_gain_code, /* i : normalised innovative cb. gain Q16 */
const Word16 gain_inov, /* i : gain of the unscaled innovation Q12 */
Word32 *gc_threshold,/* i/o: gain code threshold Q16 */
Word16 *code, /* i/o: innovation Q12 */
Word16 *exc2, /* i/o: adapt. excitation/total exc. Q_exc*/
const Word16 gain_pit, /* i : quantized pitch gain Q14 */
struct dispMem_fx *dm_fx, /* i/o: phase dispersion algorithm memory */
const Word16 Q_exc /* i : Q of the excitation */
)
{
Word16 tmp, fac, *pt_exc2;
Word16 i;
Word32 L_tmp;
Word16 gain_code_hi;
Word16 pit_sharp, tmp16;
Word16 excp[L_SUBFR], sc;
pit_sharp = gain_pit;
move16(); /* to remove gcc warning */
pt_exc2 = exc2 + i_subfr;
move16();
/*------------------------------------------------------------*
* Phase dispersion to enhance noise at low bit rate
*------------------------------------------------------------*/
i = 2;
move16(); /* no dispersion */
IF (Opt_AMR_WB)
{
IF ( L_sub(core_brate,ACELP_6k60) <= 0)
{
i = 0;
move16(); /* high dispersion */
}
ELSE if ( L_sub(core_brate,ACELP_8k85) <= 0)
{
i = 1;
move16(); /* low dispersion */
}
}
ELSE IF( sub(coder_type,UNVOICED) != 0)
{
test();
test();
test();
test();
IF ( L_sub(core_brate,ACELP_7k20) <= 0 )
{
i = 0;
move16(); /* high dispersion */
}
ELSE if ( ( sub(coder_type,GENERIC) == 0 || sub(coder_type,TRANSITION) == 0 || sub(coder_type,AUDIO) == 0 || sub(coder_type,INACTIVE) == 0 ) && L_sub(core_brate,ACELP_9k60) <= 0 )
{
i = 1;
move16(); /* low dispersion */
}
}
phase_dispersion_fx(norm_gain_code, gain_pit, code, i, dm_fx);
/*------------------------------------------------------------
* noise enhancer
*
* - Enhance excitation on noise. (modify gain of code)
* If signal is noisy and LPC filter is stable, move gain
* of code 1.5 dB toward gain of code threshold.
* This decreases by 3 dB noise energy variation.
*-----------------------------------------------------------*/
/* tmp = 0.5f * (1.0f - voice_fac) */
tmp = msu_r(0x40000000, voice_fac, 16384); /*Q15 */ /* 1=unvoiced, 0=voiced */
/* fac = stab_fac * tmp */
fac = mult(stab_fac, tmp); /*Q15*/
IF (L_sub(norm_gain_code, *gc_threshold) < 0)
{
L_tmp = Madd_32_16(norm_gain_code, norm_gain_code, 6226);/*Q16 */
L_tmp = L_min(L_tmp, *gc_threshold);/*Q16 */
}
ELSE
{
L_tmp = Mult_32_16(norm_gain_code, 27536);/*Q16 */
L_tmp = L_max(L_tmp, *gc_threshold); /*Q16 */
}
*gc_threshold = L_tmp;
move32(); /*Q16 */
/* gain_code = (fac * tmp) + (1.0 - fac) * gain_code ==> fac * (tmp - gain_code) + gain_code */
L_tmp = L_sub(L_tmp, norm_gain_code); /*Q16 */
norm_gain_code = Madd_32_16(norm_gain_code, L_tmp, fac);/*Q16 */
/* gain_code *= gain_inov - Inverse the normalization */
L_tmp = Mult_32_16(norm_gain_code, gain_inov); /*Q13*/ /* gain_inov in Q12 */
sc = 6;
move16();
gain_code_hi = round_fx(L_shl(L_tmp, add(Q_exc, 3))); /* in Q_exc */
/*------------------------------------------------------------*
* pitch enhancer
*
* - Enhance excitation on voiced. (HP filtering of code)
* On voiced signal, filtering of code by a smooth fir HP
* filter to decrease energy of code at low frequency.
*------------------------------------------------------------*/
test();
IF( !Opt_AMR_WB && sub(coder_type,UNVOICED) == 0 )
{
/* Copy(code, exc2, L_SUBFR) */
FOR (i = 0; i < L_SUBFR; i++)
{
pt_exc2[i] = round_fx(L_shl(L_mult(gain_code_hi, code[i]), sc)); /*Q0 */ /* code in Q12 (Q9 for encoder) */
}
}
ELSE
{
test();
test();
IF ( Opt_AMR_WB && ( L_sub(core_brate,ACELP_8k85) == 0|| L_sub(core_brate,ACELP_6k60) == 0 ) )
{
pit_sharp = shl(gain_pit, 1); /* saturation can occur here Q14 -> Q15 */
/* saturation takes care of "if (pit_sharp > 1.0) { pit_sharp=1.0; }" */
IF (sub(pit_sharp, 16384) > 0)
{
tmp16 = mult(pit_sharp, 8192);
FOR (i = 0; i < L_SUBFR; i++)
{
/* excp[i] = pt_exc2[i] * pit_sharp * 0.25 */
excp[i] = mult_r(pt_exc2[i], tmp16);
move16();
}
}
}
IF ( sub(L_frame, L_FRAME16k) == 0 )
{
/* tmp = 0.150 * (1.0 + voice_fac) */
/* 0.30=voiced, 0=unvoiced */
tmp = mac_r(0x10000000L, voice_fac, 4915);/*Q15 */
}
ELSE
{
/* tmp = 0.125 * (1.0 + voice_fac) */
/* 0.25=voiced, 0=unvoiced */
tmp = mac_r(0x10000000L, voice_fac, 4096);/*Q15 */
}
/*-----------------------------------------------------------------
* Do a simple noncasual "sharpening": effectively an FIR
* filter with coefs [-tmp 1.0 -tmp] where tmp=0...0.25.
* This is applied to code and add_fxed to exc2
*-----------------------------------------------------------------*/
/* pt_exc2[0] += code[0] - tmp * code[1] */
L_tmp = L_deposit_h(code[0]); /* if Enc :Q9 * Q15 -> Q25 */
L_tmp = L_msu(L_tmp, code[1], tmp); /* Q12 * Q15 -> Q28 */
L_tmp = L_shl(L_mult(gain_code_hi, extract_h(L_tmp)), sc);
pt_exc2[0] = msu_r(L_tmp, -32768, pt_exc2[0]);
move16();/* in Q_exc */
FOR (i = 1; i < L_SUBFR-1; i++)
{
/* pt_exc2[i] += code[i] - tmp * code[i-1] - tmp * code[i+1] */
L_tmp = L_msu(-32768, code[i], -32768);
L_tmp = L_msu(L_tmp, code[i + 1], tmp);
tmp16 = msu_r(L_tmp, code[i - 1], tmp);
L_tmp = L_shl(L_mult(gain_code_hi, tmp16), sc);
pt_exc2[i] = msu_r(L_tmp, -32768, pt_exc2[i]);
move16(); /* in Q_exc */
}
/* pt_exc2[L_SUBFR-1] += code[L_SUBFR-1] - tmp * code[L_SUBFR-2] */
L_tmp = L_deposit_h(code[L_SUBFR - 1]);/*Q28 */
L_tmp = L_msu(L_tmp, code[L_SUBFR - 2], tmp);/*Q28 */
L_tmp = L_shl(L_mult(gain_code_hi, extract_h(L_tmp)), sc);
pt_exc2[L_SUBFR - 1] = msu_r(L_tmp, -32768, pt_exc2[L_SUBFR - 1]);
move16();/* in Q_exc */
test();
test();
IF ( Opt_AMR_WB && ( L_sub(core_brate,ACELP_8k85) == 0 || L_sub(core_brate,ACELP_6k60) == 0 ) )
{
IF (sub(pit_sharp, 16384) > 0)
{
FOR (i = 0; i < L_SUBFR; i++)
{
/* excp[i] += pt_exc2[i] */
excp[i] = add(excp[i], pt_exc2[i]);
move16();
}
agc2_fx(pt_exc2, excp, L_SUBFR);
Copy(excp, pt_exc2, L_SUBFR);
}
}
}
}
/*---------------------------------------------------------*
* Enhancement of the excitation signal before synthesis
*---------------------------------------------------------*/
Word16 E_UTIL_enhancer(
Word16 voice_fac, /* i : subframe voicing estimation Q15 */
Word16 stab_fac, /* i : LP filter stability measure Q15 */
Word32 gain_code, /* i : innovative cb. gain 15Q16 */
Word16 gain_inov, /* i : gain of the unscaled innovation Q11 */
Word32 *gc_threshold, /* i/o: gain code threshold 15Q16 */
Word16 *code, /* i/o: innovation(in: Q9) code_exp */
Word16 *exc2, /* i/o: adapt. excitation/total exc. */
Word16 gain_pit, /* i : Quantized pitch gain 1Q14 */
Word32 *prev_gain_code, /* i/o: previous codebook gain 15Q16 */
Word16 prev_gain_pit[], /* i/o: previous pitch gain, size=6 1Q14 */
Word16 *prev_state, /* i/o: Phase dispersion algorithm memory Q0 */
Word16 coder_type, /* i : coder type */
Word16 cdk_index, /* i : */
Word16 L_subfr, /* i : length of subframe */
Word16 L_frame, /* i : frame size */
Word16 Q_new
)
{
Word16 disp_mode, i;
Word16 tmp, fac, gain;
Word32 L_tmp;
Word16 code_exp, exc2_exp;
Word16 max_cdk_index_uv;
move16();
code_exp = 15-9;
exc2_exp = 15-Q_new;
gain_inov = shr(gain_inov,1);
/*-----------------------------------------------------------------*
* Phase dispersion to enhance noise at low bit rates
*-----------------------------------------------------------------*/
max_cdk_index_uv = 10;
move16();
if ( sub(L_frame, L_FRAME16k) == 0 )
{
max_cdk_index_uv = 14;
move16();
}
disp_mode = 2; /* any=off */ move16();
test();
test();
test();
test();
IF ( ( (sub(coder_type, VOICED) != 0) && (sub(cdk_index, 2) <= 0) ) || ( (sub(coder_type, UNVOICED) == 0) && (sub(cdk_index, max_cdk_index_uv) <= 0) ) )
{
disp_mode = 0; /* high */ move16();
}
ELSE IF ( (sub(coder_type, VOICED) != 0) && (sub(cdk_index, 7) <= 0) )
{
disp_mode = 1; /* low */ move16();
}
phase_dispersion(gain_code, gain_pit,code, &code_exp, disp_mode, prev_gain_code, prev_gain_pit, prev_state, L_subfr);
/*------------------------------------------------------------*
* noise enhancer *
* ~~~~~~~~~~~~~~ *
* - Enhance excitation on noise. (modify gain of code) *
* If signal is noisy and LPC filter is stable, move gain *
* of code 1.5 dB toward gain of code threshold. *
* This decrease by 3 dB noise energy variation. *
*------------------------------------------------------------*/
fac = 0;
move16();
/* if gain_code is computed function of energy, noise enhancer is by-passed.*/
BASOP_SATURATE_WARNING_OFF
tmp = msu_r(1073741824l/*0.5f Q31*/, 16384/*0.5f Q15*/, voice_fac); /* 1=unvoiced, 0=voiced */
BASOP_SATURATE_WARNING_ON
fac = mult_r(stab_fac, tmp); /* fac in Q15 */
L_tmp = L_add(0,gain_code); /* L_tmp in 15Q16 */
IF (L_sub(L_tmp,*gc_threshold) < 0)
{
L_tmp = L_shl(Mpy_32_32(L_tmp, 1277752832l/*1.19f/2.0f Q31*/),1);
L_tmp = L_min(L_tmp, *gc_threshold);
}
ELSE
{
L_tmp = Mpy_32_32(L_tmp, 1804608000l/*1.0f/1.19f Q31*/);
L_tmp = L_max(L_tmp, *gc_threshold);
}
move32();
*gc_threshold = L_tmp; /* in 15Q16 */
/* gain = ( (fac * L_tmp) + (gain_code - fac*gain_code) ) * gain_inov */
/* exponent of L_tmp: 31-16 + 15-11 */
L_tmp = Mpy_32_16_1(L_add(Mpy_32_16_1(L_tmp, fac), L_sub(gain_code, Mpy_32_16_1(gain_code, fac))), gain_inov);
/* exponent gain: 31-16 + 15-11 - tmp */
tmp = norm_l(L_tmp);
/* exponent of code: 31-16 + 15-11 - tmp + code_exp */
move16();
code_exp = sub(add(31-16 + 15-11, code_exp), tmp);
L_tmp = L_shl(L_tmp, tmp);
gain = round_fx(L_tmp);
FOR (i=0; i<L_subfr; i++)
{
code[i] = mult_r(code[i], gain);
move16();
}
/*------------------------------------------------------------*
* pitch enhancer *
* ~~~~~~~~~~~~~~ *
* - Enhance excitation on voice. (HP filtering of code) *
* On voiced signal, filtering of code by a smooth fir HP *
* filter to decrease energy of code in low frequency. *
*------------------------------------------------------------*/
/* exponent difference of code and exc2. +1 accounts for headroom required below. */
gain = add(sub(code_exp, exc2_exp), 1);
tmp = mac_r(268435456l/*0.125f Q31*/, 4096/*0.125f Q15*/, voice_fac); /* 0.25=voiced, 0=unvoiced */
if ( sub(L_frame, L_FRAME16k) == 0 )
{
tmp = mac_r(322122560l/*0.150f Q31*/, 4915/*0.150f Q15*/, voice_fac); /* 0.30=voiced, 0=unvoiced */
}
/* exc2[0] = exc2[0] + code[0] - tmp*code[1]; */
L_tmp = L_mult(code[0], 16384);
L_tmp = L_msu0(L_tmp,tmp,code[1]);
if (gain)
{
L_tmp = L_shl(L_tmp,gain);
}
exc2[0] = msu_r(L_tmp,-32768, exc2[0]);
move16();
FOR (i=1; i<L_subfr-1; i++)
{
/* exc2[i] = exc2[i] + code[i] - tmp*(code[i+1]+code[i-1]); */
L_tmp = L_mult(code[i], 16384);
L_tmp = L_msu0(L_tmp,tmp,code[i-1]);
L_tmp = L_msu0(L_tmp,tmp,code[i+1]);
if (gain)
{
L_tmp = L_shl(L_tmp,gain);
}
exc2[i] = msu_r(L_tmp,-32768, exc2[i]);
move16();
}
/* exc2[L_subfr-1] = exc2[L_subfr-1] + code[L_subfr-1] - tmp*code[L_subfr-2]; */
L_tmp = L_mult(code[i], 16384);
L_tmp = L_msu0(L_tmp,tmp,code[i-1]);
if (gain)
{
L_tmp = L_shl(L_tmp,gain);
}
exc2[i] = msu_r(L_tmp,-32768, exc2[i]);
move16();
return code_exp;
}
/*-----------------------------------------------------------------------*
* Phase_dispersion:
*
* post-processing to enhance noise in low bit rate.
*-----------------------------------------------------------------------*/
/*======================================================================================*/
/* FUNCTION : phase_dispersion_fx() */
/*--------------------------------------------------------------------------------------*/
/* PURPOSE : post-processing to enhance noise in low bit rate. */
/*--------------------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word32) gain_code : gain of code Q16 */
/* _ (Word16) gain_pit : gain of pitch Q14 */
/* _ (Word16) mode : level, 0=hi, 1=lo, 2=off */
/*--------------------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16[]) code : code vector (Q12) */
/* _ (struct dispMem_fx*) dm_fx : static memory (size = 8) */
/* (a[0]->Q0,a[1]->Q16,a[2-7]->Q14) */
/*--------------------------------------------------------------------------------------*/
/* _ None */
/*--------------------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*======================================================================================*/
static void phase_dispersion_fx(
Word32 gain_code, /* i : gain of code Q16 */
Word16 gain_pit, /* i : gain of pitch Q14 */
Word16 code[], /* i/o: code vector */
Word16 mode, /* i : level, 0=hi, 1=lo, 2=off */
struct dispMem_fx *dm_fx /* i/o: static memory (size = 8) */
)
{
Word16 i, j, state;
Word16 *prev_gain_pit, *prev_state;
Word32 *prev_gain_code;
Word16 *code2_real, *code2_imag;
Word16 *code_real, *code_imag;
const Word16 *h_real, *h_imag;
Word16 code2[2 * L_SUBFR];
prev_state = &(dm_fx->prev_state);
prev_gain_code = &(dm_fx->prev_gain_code);
prev_gain_pit = dm_fx->prev_gain_pit;
state = 2;
move16();
if (sub(gain_pit, pitch_0_9) < 0)
{
state = 1;
move16();
}
if (sub(gain_pit, pitch_0_6) < 0)
{
state = 0;
move16();
}
FOR (i = 5; i > 0; i--)
{
prev_gain_pit[i] = prev_gain_pit[i - 1];
move16();
}
prev_gain_pit[0] = gain_pit;
move16();
IF (L_sub(L_sub(gain_code, *prev_gain_code), L_shl(*prev_gain_code, 1)) > 0)
{
state = s_min(add(state, 1), 2);
}
ELSE
{
j = 0;
move16();
FOR (i = 0; i < 6; i++)
{
j = sub(j, shr(sub(prev_gain_pit[i], pitch_0_6), 15));
}
if (sub(j, 2) > 0)
{
state = 0;
move16();
}
if (sub(sub(state, *prev_state), 1) > 0)
{
state = sub(state, 1);
}
}
*prev_gain_code = gain_code;
move32();
*prev_state = state;
move16();
/*-----------------------------------------------------------------*
* circular convolution
*-----------------------------------------------------------------*/
state = add(state, mode); /* level of dispersion */
IF (sub(state, 2) < 0)
{
r_fft_fx_lc(phs_tbl_dec, SIZE, SIZE2, NUM_STAGES, code, code2, 1);
h_real = Mid_H_phasedisp;
move16();
if (state == 0)
{
h_real = Low_H_phasedisp;
move16();
}
/* FFT Coefs are in code2 */
code2_real = code2;
move16();
code2_imag = code2 + L_SUBFR - 1;
move16();
code_real = code;
move16();
code_imag = code + L_SUBFR - 1;
move16();
h_imag = h_real + L_SUBFR - 1;
move16();
*code_real++ = mult(*code2_real++, *h_real++);
move16(); /* DC */
FOR (i=1; i<L_SUBFR/2; i++)
{
*code_real++ = msu_r(L_mult(*code2_real, *h_real), *code2_imag, *h_imag);
move16();
*code_imag-- = mac_r(L_mult(*code2_real, *h_imag), *code2_imag, *h_real);
move16();
code2_real++;
h_imag--;
h_real++;
code2_imag--;
}
*code_real++ = mult(*code2_real++, *h_real++);
move16(); /* DC */
r_fft_fx_lc(phs_tbl_dec, SIZE, SIZE2, NUM_STAGES, code, code2, 0);
FOR (i = 0; i < L_SUBFR; i++)
{
/* saturation can occur here */
code[i] = shl(code2[i], 1); /*Q12 */ move16();
}
}
}
/*======================================================================================*/
/* FUNCTION : agc2_fx() */
/*--------------------------------------------------------------------------------------*/
/* PURPOSE : AGC post-processing for lower G722.2 modes */
/*--------------------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16*[]) sig_in : postfilter input signal (Q0) */
/* _ (Word16) l_trm : subframe size */
/*--------------------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16*[]) sig_out : postfilter output signal (Q0) */
/*--------------------------------------------------------------------------------------*/
/* _ None */
/*--------------------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*======================================================================================*/
static void agc2_fx(
const Word16 *sig_in, /* i : postfilter input signal */
Word16 *sig_out, /* i/o: postfilter output signal */
const Word16 l_trm /* i : subframe size */
)
{
Word16 i, exp;
Word16 gain_in, gain_out, g0;
Word32 s;
Word16 temp;
/* calculate gain_out with exponent */
temp = shr(sig_out[0], 2);
s = L_mult0(temp, temp);
FOR (i = 1; i < l_trm; i++)
{
temp = shr(sig_out[i], 2);
s = L_mac0(s, temp, temp);
}
IF (s != 0)
{
exp = sub(norm_l(s), 1);
gain_out = round_fx(L_shl(s, exp));
/* calculate gain_in with exponent */
temp = shr(sig_in[0], 2);
s = L_mult0(temp, temp);
FOR (i = 1; i < l_trm; i++)
{
temp = shr(sig_in[i], 2);
s = L_mac0(s, temp, temp);
}
g0 = 0;
move16();
IF (s != 0)
{
i = norm_l(s);
gain_in = round_fx(L_shl(s, i));
exp = sub(exp, i);
/*---------------------------------------------------*
* g0 = sqrt(gain_in / gain_out)
*---------------------------------------------------*/
s = L_mult0(128, div_s(gain_out, gain_in)); /* s = gain_out / gain_in */
s = L_shr(s, exp); /* add exponent */
s = Isqrt(s);
g0 = round_fx(L_shl(s, 9));
}
/* sig_out(n) = gain(n) sig_out(n) */
FOR (i = 0; i < l_trm; i++)
{
sig_out[i] = round_fx(L_shl(L_mac(-8192, sig_out[i], g0), 2));
}
}
}
+78
View File
@@ -0,0 +1,78 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Enr_1_Az_fx_12Q3()
*
* Find Energy of the 1/A(z) impulse response
*-------------------------------------------------------------------*/
Word16 Enr_1_Az_fx( /* o : impulse response energy Q3 */
const Word16 Aq[], /* i : LP filter coefs Qx based on the fact that Aq[0] == 1.0 */
const Word16 len /* i : impulse response length Q0 */
)
{
Word16 h1[2*L_SUBFR];
Word16 *y;
Word16 i, j, a0, q;
Word32 L_tmp, L_tmp2;
/* Find the impulse response */
q = sub( 3, norm_s(Aq[0]) );
a0 = shr(Aq[0], q); /* Q11 */
q = sub(4, q);
/*-----------------------------------------------------------------------*
* Do the filtering (first two iters unrolled to avoid multiplies with 0)
*-----------------------------------------------------------------------*/
y = h1;
/* h1_in Q11, h1_out Q10 */
L_tmp = L_mult(a0, 1<<13); /* Q25 = L_mult(Q11,Q13) */
*y = round_fx(L_tmp); /* Q25 to Q9 */
L_tmp2 = L_mult(*y, *y); /* Q19 = L_mult(Q9,Q9) */
y++;
L_tmp = L_msu(0, Aq[1], y[-1]); /* Q23 = L_mult(Q14,Q9) */
L_tmp = L_shl(L_tmp, q);
*y = round_fx(L_tmp); /* Q25 to Q9 */
L_tmp2 = L_mac(L_tmp2, *y, *y); /* Q19 = L_mult(Q9,Q9) */
y++;
/* Skip Zeros */
FOR (i = 2; i < M; i++)
{
L_tmp = L_msu(0, Aq[1], y[-1]);
FOR (j = 2; j <= i; j++)
{
L_tmp = L_msu(L_tmp, Aq[j], y[-j]);
}
L_tmp = L_shl(L_tmp, q);
*y = round_fx(L_tmp);
L_tmp2 = L_mac(L_tmp2, *y, *y);
y++;
}
/* Normal Filtering */
FOR (; i < len; i++)
{
L_tmp = L_msu(0, Aq[1], y[-1]);
FOR (j = 2; j <= M; j++)
{
L_tmp = L_msu(L_tmp, Aq[j], y[-j]);
}
L_tmp = L_shl(L_tmp, q);
*y = round_fx(L_tmp);
L_tmp2 = L_mac(L_tmp2, *y, *y);
y++;
}
return round_fx(L_tmp2); /* Q19 to Q3 */
}
+158
View File
@@ -0,0 +1,158 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required by wmc_tool */
/*--------------------------------------------------------------------------*
* env_adj()
*
* Adjust the band energies of noise-fill and low resolution bands
*--------------------------------------------------------------------------*/
void env_adj_fx
(
const Word16 *pulses, /* i : number of pulses per band Q0 */
const Word16 length, /* i : length of spectrum Q0 */
const Word16 last_sfm, /* i : index of the last band Q0 */
Word16 *adj, /* o : adjustment factors for the envelope Q15 */
const Word16 env_stab, /* i : envelope stability Q15 */
const Word16 *sfmsize /* i : subband sizes Q0 */
)
{
Word16 i, j, group;
Word16 npul;
Word16 att_state;
Word16 start, len;
Word16 tmp, tmp_diff;
Word16 gain_adj;
Word16 idx;
att_state = 0;
move16();
len = 0;
move16();
start = 0;
move16();
/* Find attenuation levels */
FOR( i = 0; i <= last_sfm ; i++ )
{
group = sub(shr(sfmsize[i],3),1);
npul = pulses[i];
move16();
IF( sub(length, L_FRAME32k) == 0 )
{
IF( npul == 0 )
{
/* Noise filled band */
IF ( sub(group,1) <= 0 )
{
test();
test();
test();
test();
IF ( i > 0 && pulses[i-1] != 0 && pulses[i+1] != 0 )
{
adj[i] = 11796; /* Q15, 0.36f */ move16();
}
ELSE IF ( i > 0 && ( pulses[i-1] == 0 || pulses[i+1] == 0) )
{
adj[i] = 17695; /* Q15, 0.54f */ move16();
}
ELSE
{
adj[i] = 23593; /* Q15, 0.72f */ move16();
}
}
ELSE IF ( sub(i,last_sfm) < 0 )
{
test();
IF ( pulses[i-1] != 0 && pulses[i+1] != 0 )
{
adj[i] = 17695; /* Q15, 0.54f */ move16();
}
ELSE
{
adj[i] = 23593; /* Q15, 0.72f */ move16();
}
}
ELSE
{
adj[i] = 23593; /* Q15, 0.72f */ move16();
}
if( att_state == 0 )
{
start = i;
move16();
}
len = add(len,1);
move16();
att_state = 1;
move16();
}
ELSE
{
adj[i] = MAX_16; /* Q15, 1.0f (saturated) */
IF( sub(att_state, 1) == 0 ) /* End of attenuation region found */
{
/* tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); */
tmp = round_fx(L_shl(L_mult0(s_max( 0, sub(len, ENV_ADJ_START_FX)), ENV_ADJ_INV_INCL_FX),16)); /* Q15 (15+16-16) */
tmp_diff = sub(MAX_16, tmp); /* Q15 */ move16();
FOR( j = start; j < i ; j++ )
{
/* adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); */
adj[j] = s_max(add(tmp, mult(tmp_diff, adj[j])), env_stab); /* Q15 (15+15-15) */ move16();
}
len = 0;
move16();
att_state = 0;
move16();
}
}
}
/* length == L_FRAME16k */
ELSE
{
/* Calculate low accuracy band attenuation */
gain_adj = 32767; /* Q15, 1.0f (saturated) */ move16();
test();
IF( npul > 0 && sub(npul, MAX_P_ATT) < 0 )
{
/*idx = (short)(npul * att_step[group] + 0.5f) - 1; */
idx = sub(mult_r(shl(npul,2),att_step_fx[group]), 1); /* Q0 (2+13+1-16) */
if( sub(idx, MAX_P_ATT) < 0 )
{
gain_adj = gain_att_fx[idx]; /* Q15 */ move16();
}
}
adj[i] = gain_adj;
move16();
}
}
/* Check if the sequence ended with an attenuation region */
IF( sub(att_state, 1) == 0 )
{
/* tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); */
tmp = round_fx(L_shl(L_mult0(s_max( 0, sub(len, ENV_ADJ_START_FX)), ENV_ADJ_INV_INCL_FX),16)); /* Q15 (15+16-16) */
tmp_diff = sub(MAX_16, tmp); /* Q15 */ move16();
FOR( j = start; j < i ; j++ )
{
/* adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); */
adj[j] = s_max(add(tmp, mult(tmp_diff, adj[j])), env_stab); /* Q15 (15+15-15) */ move16();
}
}
return;
}
+188
View File
@@ -0,0 +1,188 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h" /* required by wmc_tool */
/*--------------------------------------------------------------------------*
* Local constants
*--------------------------------------------------------------------------*/
#define ENV_STAB_SMO_HO 10 /* number of hangover frames when switching from music to speech state */
/*--------------------------------------------------------------------------*/
/* Function env_stability_fx */
/* ~~~~~~~~~~~~~~~~~~~~~ */
/* */
/* Envelope stability measure */
/*--------------------------------------------------------------------------*/
Word16 env_stability_fx( /* in Q15 */
const Word16 *ynrm, /*i: Norm vector for current frame */
const Word16 nb_sfm, /*i: Number of sub-bands */
Word16 *mem_norm, /*i/o: Norm vector memory from past frame */
Word16 *mem_env_delta /*i/o: Envelope stability memory for smoothing in Q12 */
)
{
Word16 env_delta;
Word16 env_stab;
Word16 tmp, tmp_stab;
Word16 i;
Word16 exp, exp2;
Word32 L_tmp, L_env_delta;
Word16 inv_nb_sfm;
/* Calculate envelope stability parameter */
L_env_delta = L_deposit_l(0);
FOR (i = 0; i < nb_sfm; i++)
{
tmp = sub(mem_norm[i],ynrm[i]);
L_env_delta = L_mac0(L_env_delta, tmp, tmp);
mem_norm[i] = ynrm[i];
move16();
}
inv_nb_sfm = 19418; /* Q19 */ move16();
if (nb_sfm == 26)
{
inv_nb_sfm = 20165; /* Q19 */ move16();
}
exp = norm_l(L_env_delta);
L_env_delta = Mult_32_16(L_shl(L_env_delta, exp), inv_nb_sfm); /* 0+exp+19-15 */
L_tmp = Sqrt_l(L_env_delta, &exp2); /* exp+4+31+exp2 */
exp = add(35, add(exp, exp2));
if ( sub(s_and(exp, 1), 1) == 0 )
{
L_tmp = Mult_32_16(L_tmp, 23170); /* 1/sqrt(2) in Q15 */
}
exp = shr(exp, 1);
env_delta = round_fx(L_shl(L_tmp, sub(26, exp))); /* Q10 */
L_tmp = L_mult0(26214, env_delta); /* 26214 is 0.1 in Q18. Q28 */
L_tmp = L_mac(L_tmp, 29491, *mem_env_delta); /* 29491 is 0.9 in Q15. Q28 */
*mem_env_delta = round_fx(L_tmp); /* Q12 */
Overflow = 0;
move16();
env_delta = round_fx(L_shl(L_tmp, 1)); /* Q13 */
IF (Overflow != 0) /* Saturated due to the above up-shifting operation. */
{
return stab_trans_fx[L_STAB_TBL-1]; /* The highest quantized index. */
}
/* If tmp_stab > (D_STAB_TBL*L_STAB_TBL + M_STAB_TBL), i.e., 0.103138*10+2.51757=3.603137,
* the quantized index is equal to 9. Hence, we only need to worry about any tmpStab < 4.
* In this case, Q13 is good enough.
*/
tmp_stab = sub(env_delta, M_STAB_TBL_FX); /* in Q13 */
tmp_stab = abs_s(tmp_stab);
/* Table lookup for smooth transitions
* First, find the quantization level, i, of tmpStab. */
#if L_STAB_TBL > 10
#error env_stability_fx: Use more efficient usquant()
#endif
tmp_stab = sub(tmp_stab, HALF_D_STAB_TBL_FX); /* in Q13 */
FOR (i = 0; i < L_STAB_TBL-1; i++)
{
IF (tmp_stab < 0)
{
BREAK;
}
ELSE
{
tmp_stab = sub(tmp_stab, D_STAB_TBL_FX); /* in Q13 */
}
}
env_stab = stab_trans_fx[i];
move16();
if(sub(env_delta, M_STAB_TBL_FX) < 0)
{
env_stab = sub(0x7FFF,stab_trans_fx[i]);
}
return env_stab;
}
/*--------------------------------------------------------------------------*
* env_stab_smo_fx()
*
*
*--------------------------------------------------------------------------*/
Word16 env_stab_smo_fx( /* Q0 */
Word16 env_stab, /*i : env_stab value Q15 */
Word16 *env_stab_state_p, /*i/o: env_stab state probabilities Q15 */
Word16 *ho_cnt /*i/o: hangover counter for speech state */
)
{
Word16 state, prev_state;
Word16 maxval, pp[NUM_ENV_STAB_PLC_STATES], pa[NUM_ENV_STAB_PLC_STATES];
Word16 i;
Word16 tmp, sum, exp;
/* get previous state */
prev_state = maximum_fx(env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval);
/* assume two states: speech(0), music(1) */
/* set a posteriori likelihoods for the two states according to env_stab */
/* re-scale. Unclear if needed */
/* env_stab = (env_stab - stab_trans_fx[L_STAB_TBL-1])/(1-2*stab_trans_fx[L_STAB_TBL-1]); */
tmp = sub(env_stab, stab_trans_fx[L_STAB_TBL-1]);
tmp = round_fx(L_shl(L_mult(tmp, INV_STAB_TRANS_FX), 1)); /* Q15 */
pp[0] = sub(32767, tmp);
move16(); /* 1 in Q15 */
pp[1] = tmp;
move16();
/* calculate a priori likelihoods */
pa[0] = round_fx(Dot_product(env_stab_tp_fx[0], env_stab_state_p, NUM_ENV_STAB_PLC_STATES)); /* Q15*/
pa[1] = round_fx(Dot_product(env_stab_tp_fx[1], env_stab_state_p, NUM_ENV_STAB_PLC_STATES));
/* multiply elementwise with a posteriori likelihoods */
sum = 0;
move16();
FOR (i = 0; i < NUM_ENV_STAB_PLC_STATES; i++)
{
env_stab_state_p[i] = mult_r(pa[i], pp[i]);
move16(); /* Q15 */
sum = add(sum, env_stab_state_p[i]);
}
/* renormalize state probabilities */
exp = norm_s(sum);
tmp = div_s(16384, shl(sum, exp)); /* Q(14-exp) */
/*tmp = shl(tmp, add(exp, 1));*/ /* Q15 */
FOR (i = 0; i < NUM_ENV_STAB_PLC_STATES; i++)
{
env_stab_state_p[i] = round_fx(L_shl(L_mult(env_stab_state_p[i], tmp), add(exp, 1))); /* Q15 */
}
/* find maximum index as return value */
state = maximum_fx(env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval);
/* apply some hangover for speech */
test();
if (state == 0 && sub(prev_state, 1) == 0)
{
*ho_cnt = ENV_STAB_SMO_HO;
move16();
}
IF (*ho_cnt > 0)
{
*ho_cnt = sub(*ho_cnt, 1);
move16();
}
return state;
}
+160
View File
@@ -0,0 +1,160 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "math_op.h" /* WMOPS macros */
#include "stl.h" /* required by wmc_tool */
/*--------------------------------------------------------------------------*
* env_stab_transient_detect()
*
* Transient detector for envelope stability measure
*--------------------------------------------------------------------------*/
void env_stab_transient_detect_fx(
const Word16 is_transient, /* i: Transient flag */
const Word16 length, /* i : Length of spectrum (32 or 48 kHz) */
const Word16 norm[], /* i : quantization indices for norms */
Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover (Q0) */
Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection (Q13) */
const Word16 HQ_mode, /* i : HQ coding mode */
const Word16 bin_th, /* i : HVQ cross-over frequency bin */
const Word32 *L_coeff, /* i : Coded spectral coefficients */
const Word16 Qcoeff /* i : Q of coded spectral coefficients */
)
{
Word16 i, blk, norm_ind, sqrt_exp, bin_th_1, temp, sh;
Word32 L_e_frame, L_temp, L_d_max;
Word32 L_energy_lt_local;
Word32 L_E_sub[4];
Word32 L_delta_e_sub;
L_energy_lt_local = *L_energy_lt;
move32();
L_d_max = L_deposit_l(0);
L_e_frame = L_deposit_l(0);
temp = 32;
move16();
IF( sub(HQ_mode,HQ_HVQ) == 0 )
{
FOR (i = 0; i < bin_th; i++) /* find adaptive shift */
{
temp = s_min(temp,norm_l(L_coeff[i]));
}
sh = sub(temp,2); /* scale such that 2 msbs are not used, the resulting adaptive Qcoeff will be: Qcoeff+sh-16 */
FOR (i = 0; i < bin_th; i++) /* Maximum number of loop runs 320 */
{
temp = extract_h(L_shl(L_coeff[i],sh));
L_e_frame = L_mac(L_e_frame,temp,temp); /* Q(2*(Qcoeff+sh-16)+1)=Q(2*(Qcoeff+sh)-31 */
}
bin_th_1 = INV_HVQ_THRES_BIN_24k;
move16();
if (sub(bin_th, HVQ_THRES_BIN_32k) == 0)
{
bin_th_1 = INV_HVQ_THRES_BIN_32k;
move16();
}
L_temp = Mult_32_16(L_e_frame,bin_th_1); /* Q(2*(Qcoeff-16+sh)+1+21-15) -> Q(2*(Qcoeff+sh)-25) */
L_e_frame = Sqrt_l(L_temp,&sqrt_exp);
L_e_frame = L_shr(L_e_frame, add(sub(add(sh,Qcoeff),10),shr(sqrt_exp,1))); /* Adjust by (Qcoeff+sh-10) to fixed Q13: Qcoeff+sh+(-25+31)/2 - (Qcoeff+sh-10) -> Q13 */
IF ( L_sub(L_e_frame, ENERGY_TH_FX) > 0 )
{
L_energy_lt_local = Mult_32_16(*L_energy_lt, ENERGY_LT_BETA_FX);
L_temp = Mult_32_16(L_e_frame, ENERGY_LT_BETA_1_FX);
*L_energy_lt = L_add(L_energy_lt_local,L_temp);
move32();
}
IF (*no_att_hangover > 0)
{
(*no_att_hangover) = sub((*no_att_hangover), 1);
move16();
}
}
ELSE
{
L_e_frame = L_deposit_l(0);
test();
IF (is_transient && sub(length,L_FRAME32k) == 0)
{
/* Measure subframe energies */
FOR (blk = 0; blk < NUM_SUBFRAMES; blk++)
{
L_E_sub[blk] = L_deposit_l(0); /* Q9 */
FOR (i=0; i<BANDS_PER_SUBFRAMES; i++) /* 9 times -> < 2^4 */
{
norm_ind = subf_norm_groups_fx[blk][i];
move16();
L_E_sub[blk] = L_add(L_E_sub[blk],L_shr(dicn_fx[norm[norm_ind]],4));
move32(); ; /* Q10 */
}
L_E_sub[blk] = Mult_32_16(L_E_sub[blk], INV_BANDS_PER_SUBFRAMES);
move32(); /* Q(10+17-15) -> Q12 */
L_e_frame = L_add(L_e_frame,L_E_sub[blk]); /* Q12 */
}
/* Test for transient */
/* if (e_frame > ENERGY_TH * NUM_SUBFRAMES) */
IF (L_sub(L_e_frame, ENERGY_TH_NUM_SUBFRAMES) > 0)
{
FOR (blk = 0; blk < NUM_SUBFRAMES-1; blk++)
{
L_delta_e_sub = L_sub(L_E_sub[blk+1],L_E_sub[blk]); /* Q12 */
if (L_sub(L_delta_e_sub,L_d_max)>0)
{
L_d_max = L_add(L_delta_e_sub,0); /* L_d_max is NOT normalized with *energy_lt */
}
}
}
}
ELSE
{
/* Update long-term energy measure */
L_e_frame = L_deposit_l(0); /* Q9 */
FOR (i = 0; i < SFM_N_ENV_STAB; i++) /* 27 times -> < 2^5 */
{
L_e_frame = L_add(L_e_frame,L_shr(dicn_fx[norm[i]],5));
/* Q9 */
}
L_e_frame = Mult_32_16(L_e_frame, INV_SFM_N_ENV_STAB); /* Q(9+19-15) -> Q13 */
IF ( L_sub(L_e_frame, ENERGY_TH_FX) > 0 )
{
L_energy_lt_local = Mult_32_16(*L_energy_lt, ENERGY_LT_BETA_FX);
L_temp = Mult_32_16(L_e_frame, ENERGY_LT_BETA_1_FX);
*L_energy_lt = L_add(L_energy_lt_local,L_temp);
move32();
}
}
/* Add hang-over for conservative application of stability dependent attenuation */
/* -> Note: L_d_max not normalized with *energy_lt */
/* Hence, we compare L_d_max/DELTA_TH with *energy_lt */
IF (L_sub(Mult_32_16(L_d_max, INV_DELTA_TH),L_energy_lt_local) > 0) /* Q13 = Q(12 + 16 -15) */
{
*no_att_hangover = ATT_LIM_HANGOVER;
move16();
}
ELSE if (*no_att_hangover > 0)
{
*no_att_hangover = sub(*no_att_hangover,1);
move16();
}
}
return;
}
+265
View File
@@ -0,0 +1,265 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#include "basop_mpy.h"
#include "basop_util.h"
/*======================================================================*/
/* FUNCTION : est_tilt_fx() */
/*-----------------------------------------------------------------------*/
/* PURPOSE : Estimate spectral tilt based on the relative E of adaptive */
/* and innovative excitations */
/* */
/*-----------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16 *) exc : adaptive excitation vector Q0 */
/* _ (Word16) gain_pit : adaptive gain Q14 */
/* _ (Word16 *) code : algebraic exctitation vector Q12 */
/* _ (Word32) gain_code : algebraic code gain Q16 */
/* _ (Word16) Q_exc : Scaling factor of excitation Q0 */
/*-----------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16 *) voice_fac : voicing factor Q15 */
/*-----------------------------------------------------------------------*/
/* INPUT OUTPUT ARGUMENTS */
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ (Word16) tolt_code : tilt of the code Q15 */
/*=======================================================================*/
Word16 est_tilt_fx( /* o : tilt of the code Q15 */
const Word16 *exc, /* i : adaptive excitation vector Qx */
const Word16 gain_pit, /* i : adaptive gain Q14 */
const Word16 *code, /* i : algebraic exctitation vector Q9 */
const Word32 gain_code, /* i : algebraic code gain Q16 */
Word16 *voice_fac, /* o : voicing factor Q15 */
const Word16 Q_exc /* i : Scaling factor of excitation Q0 */
)
{
Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
Word32 L_tmp;
Word16 tilt_code;
ener1 = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp1));
exp1 = sub(exp1, add(Q_exc, Q_exc));
L_tmp = L_mult(gain_pit, gain_pit); /* energy of pitch excitation */
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
ener1 = mult(ener1, tmp);
exp1 = sub(sub(exp1, exp), 10); /* 10 -> gain_pit Q14 to Q9 */
ener2 = extract_h(Dot_product12(code, code, L_SUBFR, &exp2));
exp = norm_l(gain_code);
tmp = extract_h(L_shl(gain_code, exp));
tmp = mult(tmp, tmp); /* energy of innovative code excitation */
ener2 = mult(ener2, tmp);
exp2 = sub(exp2, add(exp, exp));
i = sub(exp1, exp2);
BASOP_SATURATE_WARNING_OFF
ener1 = shr(ener1, sub(1, s_min(i, 0)));
ener2 = shr(ener2, add(s_max(0, i), 1));
BASOP_SATURATE_WARNING_ON
tmp = sub(ener1, ener2);
ener1 = add(add(ener1, ener2), 1);
/* find voice factor (1=voiced, -1=unvoiced) */
exp = div_s(abs_s(tmp), ener1);
if (tmp < 0)
{
exp = negate(exp);
}
*voice_fac = exp;
move16();
/* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
/* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
tilt_code = mac_r(8192L*65536-0x8000, *voice_fac, 8192); /*Q15 */
return tilt_code;
}
/*-------------------------------------------------------------------*
* Est_tilt2:
*
* Estimate spectral tilt based on the relative E of adaptive
* and innovative excitations
*-------------------------------------------------------------------*/
Word16 Est_tilt2( /* o : tilt of the code */
const Word16 *exc, /* i : adaptive excitation vector Qx */
const Word16 gain_pit, /* i : adaptive gain Q14 */
const Word16 *code, /* i : algebraic exctitation vector Q9 */
const Word32 gain_code, /* i : algebraic code gain Q16 */
Word16 *voice_fac, /* o : voicing factor Q15 */
const Word16 Q_exc /* i : Scaling factor of excitation Q0 */
)
{
Word16 i, tmp, exp, ener1, exp1, ener2, exp2;
Word32 L_tmp;
Word16 tilt_code;
/* Scale exc to avoid overflow */
ener1 = extract_h(Energy_scale(exc, L_SUBFR, Q_exc, &exp1));
exp1 = sub(exp1, add(Q_exc, Q_exc));
L_tmp = L_mult(gain_pit, gain_pit); /* energy of pitch excitation */
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
ener1 = mult(ener1, tmp);
exp1 = sub(sub(exp1, exp), 10); /* 10 -> gain_pit Q14 to Q9 */
ener2 = extract_h(Dot_product12(code, code, L_SUBFR, &exp2));
exp = norm_l(gain_code);
tmp = extract_h(L_shl(gain_code, exp));
tmp = mult(tmp, tmp); /* energy of innovative code excitation */
ener2 = mult(ener2, tmp);
exp2 = sub(exp2, add(exp, exp));
i = sub(exp1, exp2);
ener1 = shr(ener1, sub(1, s_min(i, 0)));
ener2 = shr(ener2, add(s_max(0, i), 1));
tmp = sub(ener1, ener2);
ener1 = add(add(ener1, ener2), 1);
/* find voice factor (1=voiced, -1=unvoiced) */
exp = div_s(abs_s(tmp), ener1);
if (tmp < 0)
{
exp = negate(exp);
}
*voice_fac = exp;
move16();
/* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
/* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */
tilt_code = mac_r(8192L*65536-0x8000, *voice_fac, 8192);
return tilt_code;
}
/*---------------------------------------------------------*
* Find voice factor and tilt code *
*---------------------------------------------------------*/
void E_UTIL_voice_factor( Word16 *exc, /* i : pointer to the excitation frame Q_new */
Word16 i_subfr, /* i : subframe index */
Word16 *code, /* i : innovative codebook Q9 */
Word16 gain_pit, /* i : adaptive codebook gain 1Q14 */
Word32 gain_code, /* i : innovative cb. gain 15Q16 */
Word16 *voice_fac, /* o : subframe voicing estimation Q15 */
Word16 *tilt_code, /* o : tilt factor Q15 */
Word16 L_subfr, /* i : subframe length */
Word16 flag_tilt, /* i : Flag for triggering new voice factor tilt*/
Word16 Q_new, /* i : excitation buffer format */
Word16 shift /* i : scaling to get 12bit */
)
{
Word16 i, e, e2, stmp, exp_ener, fac;
Word32 ener, tmp, num;
BASOP_SATURATE_ERROR_ON;
IF(shift != 0)
{
fac = shl(0x4000,add(1,shift));
/* energy of pitch excitation */
stmp = mult_r(exc[0+i_subfr], fac); /* remove fac bits */
ener = L_mac0(0L,stmp, stmp);
FOR (i=1; i<L_subfr; i++)
{
stmp = mult_r(exc[i+i_subfr], fac); /* remove fac bits */
ener = L_mac0(ener, stmp, stmp);
}
}
ELSE
{
ener = L_mult0(exc[0+i_subfr], exc[0+i_subfr]);
FOR (i=1; i<L_subfr; i++)
{
ener = L_mac0(ener, exc[i+i_subfr], exc[i+i_subfr]); /* Q_new -> exponent = (15-Q_new)*2+1 */
}
}
/* exponent of ener: (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) */
exp_ener = norm_l(ener);
if(ener == 0)
{
exp_ener = 31;
move16();
}
ener = L_shl(ener,exp_ener);
e2 = norm_s(gain_pit);
gain_pit = shl(gain_pit,e2);
ener = Mpy_32_16_1(ener, mult_r(gain_pit, gain_pit));
/* energy of innovative code excitation */
tmp = L_deposit_l(1);
FOR (i=0; i<L_subfr; i++)
{
tmp = L_mac0(tmp, code[i], code[i]); /* 6Q9 -> 13Q18 */
}
/* exponent of tmp: 2*(15-9)+1+2*(15-e)) */
e = norm_l(gain_code);
gain_code = L_shl(gain_code, e);
tmp = Mpy_32_32(tmp, Mpy_32_32(gain_code,gain_code));
/* find voice factor (1=voiced, -1=unvoiced) */
/*i = (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) - (2*(15-9)+1 + 2*(15-e));*/
i = sub(sub(sub(sub(sub(33,add(shift,shift)),add(Q_new,Q_new)),exp_ener),add(e2,e2)),sub(43,add(e,e)));
IF(i >= 0)
{
ener = L_shr(ener,1);
tmp = L_shr(tmp, add(1,i));
}
ELSE
{
tmp = L_shr(tmp,1);
BASOP_SATURATE_WARNING_OFF
ener = L_shr(ener, sub(1,i));
BASOP_SATURATE_WARNING_ON
}
*voice_fac = 0;
move16();
num = L_sub(ener, tmp);
IF(num != 0)
{
BASOP_SATURATE_WARNING_OFF /* Allow saturating the voice factor because if has a limited range by definition. */
*voice_fac = divide3232(num, L_add(ener, tmp));
move16();
BASOP_SATURATE_WARNING_ON
}
/* find tilt of code for next subframe */
IF (flag_tilt==0)
{
/*Between 0 (=unvoiced) and 0.5 (=voiced)*/
move16();
*tilt_code = add(8192/*0.25f Q15*/, mult_r(8192/*0.25f Q15*/, *voice_fac));
}
ELSE IF (flag_tilt==1)
{
/*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
move16();
*tilt_code = add(mult_r(4096/*0.125f Q15*/, *voice_fac), 12288/*0.125f+0.25f Q15*/);
}
ELSE
{
/*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
move16();
*tilt_code = add(mult_r(4588/*0.14f Q15*/, *voice_fac), 13763/*0.14f+0.28f Q15*/);
}
BASOP_SATURATE_ERROR_OFF;
}
File diff suppressed because it is too large Load Diff
+3827
View File
File diff suppressed because it is too large Load Diff
+2832
View File
File diff suppressed because it is too large Load Diff
+431
View File
@@ -0,0 +1,431 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h"
/*------------------------------------------------------------------
*
* This is an implementation of decimation-in-time FFT algorithm for
* real sequences. The techniques used here can be found in several
* books, e.g., i) Proakis and Manolakis, "Digital Signal Processing",
* 2nd Edition, Chapter 9, and ii) W.H. Press et. al., "Numerical
* Recipes in C", 2nd Edition, Chapter 12.
*
* Input - There are two inputs to this function:
*
* 1) An integer pointer to the input data array
* 2) An integer value which should be set as +1 for FFT
* and some other value, e.g., -1 for ifFT
*
* Output - There is no return value.
* The input data are replaced with transformed data. if the
* input is a real time domain sequence, it is replaced with
* the complex FFT for positive frequencies. The FFT value
* for DC and the foldover frequency are combined to form the
* first complex number in the array. The remaining complex
* numbers correspond to increasing frequencies. if the input
* is a complex frequency domain sequence arranged as above,
* it is replaced with the corresponding time domain sequence.
*
* Notes:
*
* 1) This function is designed to be a part of a noise supp-
* ression algorithm that requires 128-point FFT of real
* sequences. This is achieved here through a 64-point
* complex FFT. Consequently, the FFT size information is
* not transmitted explicitly. However, some flexibility
* is provided in the function to change the size of the
* FFT by specifying the size information through "define"
* statements.
*
* 2) The values of the complex sinusoids used in the FFT
* algorithm are computed once (i.e., the first time the
* r_fft function is called) and stored in a table. To
* further speed up the algorithm, these values can be
* precomputed and stored in a ROM table in actual DSP
* based implementations.
*
* 3) In the c_fft function, the FFT values are divided by
* 2 after each stage of computation thus dividing the
* final FFT values by 64. No multiplying factor is used
* for the ifFT. This is somewhat different from the usual
* definition of FFT where the factor 1/N, i.e., 1/64, is
* used for the ifFT and not the FFT. No factor is used in
* the r_fft function.
*
* 4) Much of the code for the FFT and ifFT parts in r_fft
* and c_fft functions are similar and can be combined.
* They are, however, kept separate here to speed up the
* execution.
*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*
* c_fft_fx:
*
* Computes the complex part of the split-radix FFT
*------------------------------------------------------------------------*/
static void c_fft_fx(
const Word16 *phs_tbl, /* i : Table of phases */
Word16 SIZE, /* i : Size of the FFT */
Word16 NUM_STAGE, /* i : Number of stages */
const Word16 *in_ptr, /* i : coefficients in the order re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */
Word16 *out_ptr, /* o : coefficients in the order re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */
/* in_ptr & out_ptr must not overlap! */
const Word16 isign) /* i : 1=fft, otherwise it is ifft*/
{
Word16 i, j, k, ii, jj, kk, ji, kj;
Word32 L_tmp1, L_tmp2;
Word16 tmp1,tmp2,tmp3,tmp4;
const Word16 *table_ptr;
const Word16 *input_ptr1,*input_ptr2,*input_ptr3,*input_ptr4;
/* Setup Reorder Variables */
table_ptr = NULL;
SWITCH (SIZE)
{
case 1024:
table_ptr = FFT_REORDER_1024;
BREAK;
case 512:
table_ptr = FFT_REORDER_512;
BREAK;
case 256:
table_ptr = FFT_reorder_256;
BREAK;
case 128:
table_ptr = FFT_REORDER_128;
BREAK;
case 64:
table_ptr = FFT_reorder_64;
BREAK;
}
/* The FFT part */
IF (isign != 0)
{
/* Unrolled 1st/2nd Stage
* 1) to take advantage of Table Values (0 & +/- 16384)
* 2) to perform reordering of Input Values
*/
FOR (k = 0; k < SIZE; k += 8)
{
/*
* This loop use:
* 4 Word16 (tmp1...tmp4)
* 2 Word32 (L_tmp1 & L_tmp2)
* 4 Pointers (table_ptr, input_ptr1, input_ptr2, input_ptr3)
*
* The addition of 'in_ptr' + and index value from 'reorder_ptr'
* is counted as a move16()
*/
input_ptr1 = in_ptr + *table_ptr++;
L_tmp1 = L_mult(*input_ptr1++, 16384);
L_tmp2 = L_mult(*input_ptr1, 16384);
input_ptr1 = in_ptr + *table_ptr++;
tmp1 = msu_r(L_tmp1, *input_ptr1, 16384);
tmp3 = mac_r(L_tmp1, *input_ptr1++, 16384);
input_ptr2 = in_ptr + *table_ptr++;
input_ptr3 = in_ptr + *table_ptr++;
L_tmp1 = L_mult(*input_ptr2++, 16384);
tmp2 = mac_r(L_tmp1, *input_ptr3, 16384);
tmp4 = msu_r(L_tmp1, *input_ptr3++, 16384);
L_tmp1 = L_mult(tmp3, 16384);
out_ptr[k] = mac_r(L_tmp1, tmp2, 16384);
move16();
out_ptr[k+4] = msu_r(L_tmp1, tmp2, 16384);
move16();
tmp2 = mac_r(L_tmp2, *input_ptr1, 16384);
tmp3 = msu_r(L_tmp2, *input_ptr1, 16384);
L_tmp2 = L_mult(*input_ptr2, 16384);
L_tmp1 = L_mult(tmp1, 16384);
tmp1 = msu_r(L_tmp2, *input_ptr3, 16384);
out_ptr[k+2] = mac_r(L_tmp1, tmp1, 16384);
move16();
out_ptr[k+6] = msu_r(L_tmp1, tmp1, 16384);
move16();
L_tmp1 = L_mult(tmp2, 16384);
tmp2 = mac_r(L_tmp2, *input_ptr3, 16384);
out_ptr[k+1] = mac_r(L_tmp1, tmp2, 16384);
move16();
out_ptr[k+5] = msu_r(L_tmp1, tmp2, 16384);
move16();
L_tmp1 = L_mult(tmp3, 16384);
out_ptr[k+3] = msu_r(L_tmp1, tmp4, 16384);
move16();
out_ptr[k+7] = mac_r(L_tmp1, tmp4, 16384);
move16();
}
/* Remaining Stages */
FOR (i = 2; i < NUM_STAGE; i++)
{
/* i is stage counter */
jj = shl(2, i); /* FFT size */
kk = shl(jj, 1); /* 2 * FFT size */
ii = shr(SIZE, i);
ji = 0;
move16(); /* ji is phase table index */
FOR (j = 0; j < jj; j += 2)
{
/* j is sample counter */
FOR (k = j; k < SIZE; k += kk)
{
/* k is butterfly top */
kj = add(k, jj); /* kj is butterfly bottom */
/* Butterfly computations */
L_tmp1 = L_msu(L_mult(*(out_ptr + kj), phs_tbl[ji]),
*(out_ptr + kj + 1), phs_tbl[ji + 1]);
L_tmp2 = L_mac(L_mult(*(out_ptr + kj + 1), phs_tbl[ji]),
*(out_ptr + kj), phs_tbl[ji + 1]);
out_ptr[kj] = mac_r(L_negate(L_tmp1), out_ptr[k], 16384);
move16();
out_ptr[kj+1] = mac_r(L_negate(L_tmp2), out_ptr[k+1], 16384);
move16();
out_ptr[k] = mac_r(L_tmp1, out_ptr[k], 16384);
move16();
out_ptr[k+1] = mac_r(L_tmp2, out_ptr[k+1], 16384);
move16();
}
ji = add(ji, ii);
}
}
}
ELSE /* The ifFT part */
{
/* Unrolled 1st/2nd Stage
* 1) to take advantage of Table Values (0 & +/- 16384)
* 2) to perform reordering of Input Values
*/
FOR (k = 0; k < SIZE; k += 8)
{
/*
* This loop use:
* 4 Word16 (tmp1...tmp4)
* 2 Word32 (L_tmp1 & L_tmp2)
* 5 Pointers (reorder_ptr, input_ptr1...input_ptr4)
*
* The addition of 'in_ptr' + and index value from 'reorder_ptr'
* is counted as a move16()
*/
input_ptr1 = in_ptr + *table_ptr++;
input_ptr2 = in_ptr + *table_ptr++;
input_ptr3 = in_ptr + *table_ptr++;
input_ptr4 = in_ptr + *table_ptr++;
tmp3 = sub(*input_ptr1, *input_ptr2);
tmp4 = add(*input_ptr1++, *input_ptr2++);
tmp2 = sub(input_ptr3[0], input_ptr4[0]);
tmp1 = sub(input_ptr3[1], input_ptr4[1]);
out_ptr[k+2] = sub(tmp3, tmp1);
move16();
out_ptr[k+6] = add(tmp3, tmp1);
move16();
tmp1 = sub(*input_ptr1, *input_ptr2);
out_ptr[k+3] = add(tmp1, tmp2);
move16();
out_ptr[k+7] = sub(tmp1, tmp2);
move16();
tmp1 = add(input_ptr3[0], input_ptr4[0]);
tmp3 = add(input_ptr3[1], input_ptr4[1]);
out_ptr[k] = add(tmp4, tmp1);
move16();
out_ptr[k+4] = sub(tmp4, tmp1);
move16();
tmp4 = add(*input_ptr1, *input_ptr2);
out_ptr[k+1] = add(tmp4, tmp3);
move16();
out_ptr[k+5] = sub(tmp4, tmp3);
move16();
}
table_ptr = phs_tbl + SIZE; /* access part of table that is scaled by 2 */
/* Remaining Stages */
FOR (i = 2; i < NUM_STAGE; i++)
{
/* i is stage counter */
jj = shl(2, i); /* FFT size */
kk = shl(jj, 1); /* 2 * FFT size */
ii = shr(SIZE, i);
ji = 0;
move16(); /* ji is phase table index */
FOR (j = 0; j < jj; j += 2)
{
/* j is sample counter */
/* This can be computed by successive add_fxitions of ii to ji, starting from 0
hence line-count it as a one-line add (still need to increment op count!!) */
FOR (k = j; k < SIZE; k += kk)
{
/* k is butterfly top */
kj = add(k, jj); /* kj is butterfly bottom */
/* Butterfly computations */
tmp1 = mac_r(L_mult(out_ptr[kj], table_ptr[ji]),
out_ptr[kj+1], table_ptr[ji + 1]);
tmp2 = msu_r(L_mult(out_ptr[kj+1], table_ptr[ji]),
out_ptr[kj], table_ptr[ji+1]);
out_ptr[kj] = sub(out_ptr[k], tmp1);
move16();
out_ptr[kj+1] = sub(out_ptr[k+1], tmp2);
move16();
out_ptr[k] = add(out_ptr[k], tmp1);
move16();
out_ptr[k+1] = add(out_ptr[k+1], tmp2);
move16();
}
ji = add(ji, ii);
}
}
}
}
/*--------------------------------------------------------------------------------*
* r_fft_fx:
*
* Perform FFT fixed-point for real-valued sequences of length 32, 64 or 128
*--------------------------------------------------------------------------------*/
void r_fft_fx_lc(
const Word16 *phs_tbl, /* i : Table of phase */
const Word16 SIZE, /* i : Size of the FFT */
const Word16 SIZE2, /* i : Size / 2 */
const Word16 NUM_STAGE, /* i : Number of stage */
const Word16 *in_ptr, /* i : coefficients in the order re[0], re[1], ... re[n/2], im[n/2-1], im[n/2-2], ..., im[1] */
Word16 *out_ptr, /* o : coefficients in the order re[0], re[1], ... re[n/2], im[n/2-1], im[n/2-2], ..., im[1] */
const Word16 isign /* i : 1=fft, otherwize it's ifft */
)
{
Word16 tmp2_real, tmp2_imag;
Word32 Ltmp1_real, Ltmp1_imag;
Word16 i;
Word32 Ltmp1;
const Word16 *phstbl_ptrDn;
Word16 *ptrDn;
Word16 temp[1024]; /* Accommodates real input FFT size up to 1024. */
/* Setup Pointers */
phstbl_ptrDn = &phs_tbl[SIZE-1];
/* The FFT part */
IF (isign != 0)
{
Word16 *ptRealUp, *ptRealDn, *ptImaUp, *ptImaDn;
/* Perform the complex FFT */
c_fft_fx(phs_tbl, SIZE, NUM_STAGE, in_ptr, temp, isign);
/* First, handle the DC and foldover frequencies */
out_ptr[SIZE2] = sub(temp[0], temp[1]);
move16();
out_ptr[0] = sub(add(temp[0], temp[1]), shr(NUM_STAGE, 1));
move16();/* DC have a small offset */
ptrDn = &temp[SIZE-1];
ptImaDn = &out_ptr[SIZE-1];
ptRealUp = &out_ptr[1];
ptImaUp = &out_ptr[SIZE2+1];
ptRealDn = &out_ptr[SIZE2-1];
/* Now, handle the remaining positive frequencies */
FOR (i = 2; i <= SIZE2; i += 2)
{
Ltmp1_imag = L_mult(temp[i+1], 16384);
Ltmp1_imag = L_msu(Ltmp1_imag, *ptrDn, 16384);
tmp2_real = add(temp[i+1], *ptrDn--);
Ltmp1_real = L_mult(temp[i], 16384);
Ltmp1_real = L_mac(Ltmp1_real, *ptrDn, 16384);
tmp2_imag = sub(*ptrDn--, temp[i]);
*ptRealUp++ = msu_r(L_mac(Ltmp1_real, tmp2_real, phs_tbl[i]), tmp2_imag, phs_tbl[i+1]);
move16();
*ptImaDn-- = mac_r(L_mac(Ltmp1_imag, tmp2_imag, phs_tbl[i]), tmp2_real, phs_tbl[i+1]);
move16();
Ltmp1 = L_mac(L_negate(Ltmp1_imag), tmp2_real, *phstbl_ptrDn);
Ltmp1_real = L_mac(Ltmp1_real, tmp2_imag, *phstbl_ptrDn--);
*ptImaUp++ = msu_r(Ltmp1, tmp2_imag, *phstbl_ptrDn);
move16();
*ptRealDn-- = mac_r(Ltmp1_real, tmp2_real, *phstbl_ptrDn--);
move16();
}
}
ELSE /* The ifFT part */
{
const Word16 *ptRealUp, *ptRealDn, *ptImaUp, *ptImaDn;
/* First, handle the DC and foldover frequencies */
Ltmp1 = L_mult(in_ptr[0], 16384);
temp[0] = mac_r(Ltmp1, in_ptr[SIZE2], 16384);
move16();
temp[1] = msu_r(Ltmp1, in_ptr[SIZE2], 16384);
move16();
ptrDn = &temp[SIZE-1];
/* Here we cast to Word16 * from a const Word16 *. */
/* This is ok because we use these pointers for */
/* reading only. This is just to avoid declaring a */
/* bunch of 4 other pointer with const Word16 *. */
ptImaDn = &in_ptr[SIZE-1];
ptRealUp = &in_ptr[1];
ptImaUp = &in_ptr[SIZE2+1];
ptRealDn = &in_ptr[SIZE2-1];
/* Now, handle the remaining positive frequencies */
FOR (i = 2; i <= SIZE2; i += 2)
{
Ltmp1_imag = L_mult(*ptImaDn, 16384);
Ltmp1_imag = L_msu(Ltmp1_imag, *ptImaUp, 16384);
tmp2_real = add(*ptImaDn--, *ptImaUp++);
Ltmp1_real = L_mult(*ptRealUp, 16384);
Ltmp1_real = L_mac(Ltmp1_real, *ptRealDn, 16384);
tmp2_imag = sub(*ptRealUp++, *ptRealDn--);
temp[i] = mac_r(L_msu(Ltmp1_real, tmp2_real, phs_tbl[i]), tmp2_imag, phs_tbl[i+1]);
move16();
temp[i+1] = mac_r(L_mac(Ltmp1_imag, tmp2_imag, phs_tbl[i]), tmp2_real, phs_tbl[i+1]);
move16();
Ltmp1 = L_mac(L_negate(Ltmp1_imag), tmp2_real, *phstbl_ptrDn);
Ltmp1_real = L_msu(Ltmp1_real, tmp2_imag, *phstbl_ptrDn--);
*ptrDn-- = msu_r(Ltmp1, tmp2_imag, *phstbl_ptrDn);
move16();
*ptrDn-- = msu_r(Ltmp1_real, tmp2_real, *phstbl_ptrDn--);
move16();
}
/* Perform the complex ifFT */
c_fft_fx(phs_tbl, SIZE, NUM_STAGE, temp, out_ptr, isign);
}
}
+456
View File
@@ -0,0 +1,456 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*---------------------------------------------------------------------*
* Local constants
*---------------------------------------------------------------------*/
#define INV_SQR2_FX 23170
#define N_MAX_SAS 256
/*---------------------------------------------------------------------*
* fft_rel_fx()
*
* Computes the split-radix FFT in place for the real-valued
* signal x of length n. The algorithm has been ported from
* the fortran code of [1].
*
* The function needs sine and cosine tables t_sin and t_cos,
* and the constant N_MAX_SAS. The table entries are defined as
* sin(2*pi*i) and cos(2*pi*i) for i = 0, 1, ..., N_MAX_SAS-1. The
* implementation assumes that any entry will not be needed
* outside the tables. Therefore, N_MAX_SAS and n must be properly
* set. The function has been tested with the values n = 16,
* 32, 64, 128, 256, and N_MAX_SAS = 1280.
*
* References
* [1] H.V. Sorensen, D.L. Jones, M.T. Heideman, C.S. Burrus,
* "Real-valued fast Fourier transform algorithm," IEEE
* Trans. on Signal Processing, Vol.35, No.6, pp 849-863,
* 1987.
*
* OUTPUT
* x[0:n-1] Transform coeffients in the order re[0], re[1],
* ..., re[n/2], im[n/2-1], ..., im[1].
*---------------------------------------------------------------------*/
/*MERGE fft_rel_fx and fft_rel_fx_lc */
void fft_rel_fx(
Word16 x[], /* i/o: input/output vector */
const Word16 n, /* i : vector length */
const Word16 m /* i : log2 of vector length */
)
{
Word16 i, j, k, n1, n2, n4;
Word16 step;
Word16 xt, t1, t2;
Word16 *x0, *x1, *x2;
const Word16 *s, *c;
Word16 *xi2, *xi3, *xi4, *xi1;
/*-----------------------------------------------------------------*
* Digit reverse counter
*-----------------------------------------------------------------*/
j = 0;
move16();
x0 = &x[0];
move16();
FOR (i = 0; i < n-1; i++)
{
IF (sub(i,j) < 0)
{
xt = x[j];
move16();
x[j] = *x0;
move16();
*x0 = xt;
move16();
}
x0++;
k = shr(n,1);
WHILE (sub(k,j) <= 0)
{
j = sub(j,k);
k = shr(k,1);
}
j = add(j,k);
}
/*-----------------------------------------------------------------*
* Length two butterflies
*-----------------------------------------------------------------*/
x0 = &x[0];
move16();
x1 = &x[1];
move16();
FOR (i = 0; i < n/2; i++)
{
xt = *x0;
move16();
*x0 = add(xt,*x1);
move16();
*x1 = sub(xt,*x1);
move16();
x0++;
x0++;
x1++;
x1++;
}
/*-----------------------------------------------------------------*
* Other butterflies
*
* The implementation described in [1] has been changed by using
* table lookup for evaluating sine and cosine functions. The
* variable ind and its increment step are needed to access table
* entries. Note that this implementation assumes n4 to be so
* small that ind will never exceed the table. Thus the input
* argument n and the constant N_MAX_SAS must be set properly.
*-----------------------------------------------------------------*/
n2 = 1;
move16();
/* step = N_MAX_SAS/4; */
FOR (k = 2; k <= m; k++)
{
n4 = n2;
move16();
n2 = shl(n4,1);
n1 = shl(n2,1);
step = N_MAX_SAS/n1;
x0 = x;
x1 = x + n2;
x2 = x + add(n2, n4);
FOR (i = 0; i < n; i += n1)
{
xt = *x0;
move16(); /* xt = x[i]; */
*x0 = add(xt,*x1);
move16(); /* x[i] = xt + x[i+n2]; */
*x1 = sub(xt,*x1);
move16(); /* x[i+n2] = xt - x[i+n2]; */
*x2 = negate(*x2);
move16(); /* x[i+n2+n4] = -x[i+n2+n4]; */
s = sincos_t_fx + step;
c = s + 64;
xi1 = x + add(i, 1);
xi3 = xi1 + n2;
xi2 = xi3 - 2;
xi4 = xi1 + sub(n1, 2);
FOR (j = 1; j < n4; j++)
{
t1 = add(mult_r(*xi3,*c),mult_r(*xi4,*s)); /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); */
t2 = sub(mult_r(*xi3,*s),mult_r(*xi4,*c)); /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); */
*xi4 = sub(*xi2,t2);
move16();
*xi3 = negate(add(*xi2,t2));
move16();
*xi2 = sub(*xi1,t1);
move16();
*xi1 = add(*xi1,t1);
move16();
xi4--;
xi2--;
xi3++;
xi1++;
c += step;
s += step; /* autoincrement by ar0 */
}
x0 += n1;
x1 += n1;
x2 += n1;
}
/* step = shr(step, 1); */
}
return;
}
void ifft_rel_fx(
Word16 io[], /* i/o: input/output vector */
const Word16 n, /* i : vector length */
const Word16 m /* i : log2 of vector length */
)
{
Word16 i, j, k;
Word16 step;
Word16 n2, n4, n8, i0;
Word16 is, id;
Word16 *x,*xi0, *xi1, *xi2, *xi3, *xi4, *xup1, *xdn6, *xup3, *xdn8;
Word16 xt;
Word16 r1;
Word16 t1, t2, t3, t4, t5;
const Word16 *s, *c, *s3, *c3;
Word16 cc1, cc3, ss1, ss3;
Word16 tmp;
/*-----------------------------------------------------------------*
* ifft
*-----------------------------------------------------------------*/
x = &io[-1];
move16();
n2 = shl(n,1);
FOR (k=1; k<m; k++)
{
is = 0;
move16();
id = n2;
move16();
n2 = shr(n2,1);
move16();
n4 = shr(n2,2);
move16();
n8 = shr(n4,1);
move16();
tmp = sub(n,1);
WHILE( sub(is,tmp) < 0 )
{
xi1 = x + is + 1;
move16();
xi2 = xi1 + n4;
move16();
xi3 = xi2 + n4;
move16();
xi4 = xi3 + n4;
move16();
FOR (i=is; i<n; i+= id)
{
t1 = sub(*xi1,*xi3);
*xi1 = add(*xi1,*xi3);
move16();
*xi2 = shl(*xi2,1);
move16();
*xi3 = sub(t1,shl(*xi4,1));
move16();
*xi4 = add(t1,shl(*xi4,1));
move16();
IF (sub(n4,1) != 0)
{
t1 = mult_r(sub(*(xi2+n8),*(xi1+n8)),INV_SQR2_FX);
t2 = mult_r(add(*(xi4+n8),*(xi3+n8)),INV_SQR2_FX);
*(xi1+n8) = add(*(xi1+n8),*(xi2+n8));
move16();
*(xi2+n8) = sub(*(xi4+n8),*(xi3+n8));
move16();
*(xi3+n8) = negate(shl(add(t2,t1),1));
move16();
*(xi4+n8) = shl(sub(t1,t2),1);
move16();
}
xi1 += id;
move16();
xi2 += id;
move16();
xi3 += id;
move16();
xi4 += id;
move16();
}
is = sub(shl(id,1),n2);
id = shl(id,2);
}
/*Can be acheived with a shr */
step = N_MAX_SAS/n2;
move16();
s = sincos_t_fx + step;
move16();
c = s + 64;
move16();
s3 = sincos_t_fx + i_mult2(step,3);
move16();
c3 = s3 + 64;
move16();
FOR (j=2; j<=n8; j++)
{
cc1 = *c ;
move16();
ss1 = *s;
move16();
cc3 = *c3;
move16();
ss3 = *s3;
move16();
is = 0;
move16();
id = shl(n2,1);
c += step;
move16();
s += step;
move16();
c3 += 3*step;
move16();
s3 += 3*step;
move16();
WHILE (sub(is,sub(n,1)) < 0)
{
xup1 = x + j + is;
move16();
xup3 = xup1 + shl(n4,1);
move16();
xdn6 = xup3 - shl(j,1) +2;
move16();
xdn8 = xdn6 + shl(n4,1);
move16();
FOR (i=is; i<n; i+=id)
{
t1 = sub(*xup1,*xdn6);
*xup1 = add(*xup1,*xdn6);
move16();
xup1 += n4;
move16();
xdn6 -= n4;
move16();
t2 = sub(*xdn6,*xup1);
*xdn6 = add(*xup1,*xdn6);
move16();
xdn6 += n4;
move16();
t3 = add(*xdn8,*xup3);
*xdn6 = sub(*xdn8,*xup3);
move16();
xup3 += n4;
move16();
xdn8 -= n4;
move16();
t4 = add(*xup3,*xdn8);
*xup1= sub(*xup3,*xdn8);
move16();
t5 = sub(t1,t4);
t1 = add(t1,t4);
t4 = sub(t2,t3);
t2 = add(t2,t3);
*xup3 = sub(mult_r(t1,cc3),mult_r(t2,ss3));
move16();
xup3 -= n4;
move16();
*xup3 = add(mult_r(t5,cc1),mult_r(t4,ss1));
move16();
*xdn8 = sub(mult_r(t5,ss1),mult_r(t4,cc1));
move16();
xdn8 += n4;
move16();
*xdn8 = add(mult_r(t2,cc3),mult_r(t1,ss3));
move16();
xup1 -= n4;
move16();
xup1 += id;
move16();
xup3 += id;
move16();
xdn6 += id;
move16();
xdn8 += id;
move16();
}
is = sub(shl(id,1),n2);
id = shl(id,2);
}
}
}
/*-----------------------------------------------------------------*
* Length two butterflies
*-----------------------------------------------------------------*/
is = 1;
move16();
id = 4;
move16();
WHILE (is < n)
{
xi0 = x + is ;
move16();
xi1 = xi0 + 1;
move16();
FOR (i0=is; i0<=n; i0+=id)
{
r1 = *xi0;
move16();
*xi0= add(r1,*xi1);
move16();
*xi1 = sub(r1,*xi1);
move16();
xi0 += id;
move16();
xi1 += id;
move16();
}
is = sub(shl(id,1),1);
id = shl(id,2);
}
/*-----------------------------------------------------------------*
* Digit reverse counter
*-----------------------------------------------------------------*/
j = 1;
move16();
FOR (i=1; i<n; i++)
{
IF (sub(i,j) < 0)
{
xt = x[j];
move16();
x[j] = x[i];
move16();
x[i] = xt;
move16();
}
k = shr(n, 1);
WHILE (sub(k,j) < 0)
{
j = sub(j,k);
k =shr(k, 1);
}
j = add(j,k);
}
/*-----------------------------------------------------------------*
* Normalization
*-----------------------------------------------------------------*/
tmp = div_s(1,n); /*Q15 */
FOR (i=1; i<=n; i++)
{
x[i] = mult_r(x[i],tmp);
move16();
}
return;
}
+278
View File
@@ -0,0 +1,278 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
/*--------------------------------------------------------------------------*
* fill_spectrum()
*
* Apply spectral filling by
* - filling zero-bit bands below BWE region
* - applying BWE above transition frequency
*--------------------------------------------------------------------------*/
void fill_spectrum_fx(
Word16 *coeff, /* i/o: normalized MLT spectrum / nf spectrum Q12 */
Word32 *L_coeff_out, /* i/o: Noisefilled MLT spectrum Q12 */
const Word16 *R, /* i : number of pulses per band Q0 */
const Word16 is_transient, /* i : transient flag Q0 */
Word16 norm[], /* i : quantization indices for norms Q0 */
const Word16 *hq_generic_fenv, /* i : HQ GENERIC envelope Q1 */
const Word16 hq_generic_offset, /* i : HQ GENERIC offset Q0 */
const Word16 nf_idx, /* i : noise fill index Q0 */
const Word16 length, /* i : Length of spectrum (32 or 48 kHz) Q0 */
const Word16 env_stab, /* i : Envelope stability measure [0..1] Q15 */
Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover Q0 */
Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection Q13 */
Word16 *bwe_seed, /* i/o: random seed for generating BWE input Q0 */
const Word16 hq_generic_exc_clas, /* i : BWE excitation class Q0 */
const Word16 core_sfm, /* i : index of the end band for core Q0 */
const Word16 HQ_mode, /* i : HQ mode Q0 */
Word16 noise_level[], /* i : noise levels for harmonic modes Q15 */
const Word32 L_core_brate, /* i : target bit-rate Q0 */
Word16 prev_noise_level[], /* i/o: noise factor in previous frame Q15 */
Word16 *prev_R, /* i/o: bit allocation info. in previous frame Q0 */
Word32 *prev_coeff_out, /* i/o: decoded spectrum in previous frame Q12 */
const Word16 *peak_idx, /* i : peak indices for hvq Q0 */
const Word16 Npeaks, /* i : number of peaks in hvq Q0 */
const Word16 *npulses, /* i : number of pulses per band Q0 */
const Word16 prev_is_transient, /* i : previous transient flag Q0 */
Word32 *prev_normq, /* i/o: previous norms Q14 */
Word32 *prev_env, /* i/o: previous noise envelopes Q(prev_env_Q) */
const Word16 prev_bfi, /* i : previous bad frame indicator Q0 */
const Word16 *sfmsize, /* i : Length of bands Q0 */
const Word16 *sfm_start, /* i : Start of bands Q0 */
const Word16 *sfm_end, /* i : End of bands Q0 */
Word16 *prev_L_swb_norm, /* i/o: HVQ/Harmonic mode normalization length Q0 */
const Word16 prev_hq_mode, /* i : Previous HQ mode Q0 */
const Word16 num_sfm /* i : Total number of bands Q0 */
,Word16 *prev_env_Q
,const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_GEN Q0 */
)
{
Word16 CodeBook[FREQ_LENGTH]; /* Q12 */
Word16 cb_size;
Word16 last_sfm;
Word16 CodeBook_mod[FREQ_LENGTH]; /*Q12 */
Word16 norm_adj[NB_SFM]; /*Q15 */
Word16 high_sfm;
Word16 flag_32K_env_hangover;
Word16 bin_th;
Word16 peak_pos[L_HARMONIC_EXC];
Word16 bwe_peaks[L_FRAME48k];
Word32 L_normq_v[NB_SFM]; /*Q14 */
Word16 coeff_fine[L_FRAME48k]; /*Q15 */
Word32 L_coeff_out1[L_FRAME48k]; /*Q12 */
set16_fx( peak_pos, 0, L_HARMONIC_EXC );
set16_fx( bwe_peaks, 0, L_FRAME48k );
set16_fx(norm_adj, 32767, num_sfm); /* 1.0, Q15 */
cb_size = 0;
move16();
bin_th = 0;
move16();
high_sfm = 23;
move16();
test();
IF ( sub(HQ_mode, HQ_TRANSIENT) == 0 )
{
last_sfm = sub(num_sfm, 1);
}
ELSE IF ( sub(HQ_mode,HQ_GEN_SWB) == 0 || sub(HQ_mode,HQ_GEN_FB) == 0 )
{
last_sfm = s_max(core_sfm,sub(num_env_bands,1));
}
ELSE
{
last_sfm = core_sfm;
move16();
}
IF ( sub(HQ_mode, HQ_HARMONIC) == 0 )
{
/*high_sfm = (core_brate == HQ_24k40) ? HVQ_THRES_SFM_24k-1 : HVQ_THRES_SFM_32k-3; */
high_sfm = sub(HVQ_THRES_SFM_32k, 1);
if (L_sub(L_core_brate, HQ_24k40) == 0)
{
high_sfm = sub(HVQ_THRES_SFM_24k, 1);
}
if( sub(last_sfm, high_sfm) < 0 )
{
last_sfm = high_sfm;
move16();
}
}
ELSE if ( sub(HQ_mode, HQ_HVQ) == 0 )
{
bin_th = sfm_end[last_sfm];
move16();
}
/* Transient analysis for envelope stability measure */
IF ( sub(length, L_FRAME32k) == 0 )
{
env_stab_transient_detect_fx( is_transient, length, norm, no_att_hangover, L_energy_lt, HQ_mode, bin_th, L_coeff_out, 12 );
}
test();
test();
test();
test();
IF ( sub(length, L_FRAME16k) == 0 ||
((sub(length, L_FRAME32k) == 0 && sub(HQ_mode, HQ_HARMONIC) != 0 && sub(HQ_mode, HQ_HVQ) != 0) && *no_att_hangover == 0) )
{
/* Norm adjustment function */
env_adj_fx( npulses, length, last_sfm, norm_adj, env_stab, sfmsize );
}
/*flag_32K_env_hangover = ( length == L_FRAME32k && ( (env_stab < 0.5f && *no_att_hangover == 0) || HQ_mode == HQ_HVQ ) ); */
flag_32K_env_hangover = 0;
move16();
test();
test();
test();
if ( sub(length, L_FRAME32k) == 0 && ( (sub(env_stab, 16384) < 0 && *no_att_hangover == 0) || sub(HQ_mode, HQ_HVQ) == 0 ) )
{
flag_32K_env_hangover = 1;
move16();
}
/*----------------------------------------------------------------*
* Build noise-fill codebook
*----------------------------------------------------------------*/
IF ( sub(HQ_mode, HQ_HVQ) != 0 )
{
cb_size = build_nf_codebook_fx(flag_32K_env_hangover, coeff, sfm_start, sfmsize, sfm_end, last_sfm, R, CodeBook, CodeBook_mod);
}
/*----------------------------------------------------------------*
* Prepare fine structure for Harmonic and HVQ
*----------------------------------------------------------------*/
IF ( sub(HQ_mode, HQ_HARMONIC) == 0 )
{
harm_bwe_fine_fx( R, last_sfm, high_sfm, num_sfm, norm, sfm_start, sfm_end, prev_L_swb_norm, coeff, L_coeff_out, coeff_fine );
}
ELSE IF ( sub(HQ_mode, HQ_HVQ) == 0 )
{
hvq_bwe_fine_fx( last_sfm, num_sfm, sfm_end, peak_idx, Npeaks, peak_pos, prev_L_swb_norm, L_coeff_out, bwe_peaks, coeff_fine );
}
/*----------------------------------------------------------------*
* Apply noise-fill
*----------------------------------------------------------------*/
test();
IF ( sub(HQ_mode, HQ_HVQ) != 0 && cb_size > 0 )
{
apply_noisefill_HQ_fx( R, length, flag_32K_env_hangover, L_core_brate, last_sfm, CodeBook,
CodeBook_mod, cb_size, sfm_start, sfm_end, sfmsize, coeff );
}
/*----------------------------------------------------------------*
* Normal mode BWE
*----------------------------------------------------------------*/
IF ( HQ_mode == HQ_NORMAL )
{
hq_fold_bwe_fx(last_sfm, sfm_end, num_sfm, coeff);
}
/*----------------------------------------------------------------*
* Apply noise-fill adjustment
*----------------------------------------------------------------*/
test();
test();
test();
IF( (sub(length, L_FRAME32k) >= 0 || L_sub(L_core_brate, HQ_32k) > 0 || L_sub(L_core_brate, HQ_24k40) < 0)
&& sub(HQ_mode, HQ_HVQ) != 0 )
{
apply_nf_gain_fx(nf_idx, last_sfm, R, sfm_start, sfm_end, coeff);
}
/*----------------------------------------------------------------*
* Prepare fine strucutre for HQ GENERIC
*----------------------------------------------------------------*/
test();
IF ( sub(HQ_mode, HQ_GEN_SWB) == 0 || sub(HQ_mode, HQ_GEN_FB) == 0 )
{
hq_generic_fine_fx( coeff, last_sfm, sfm_start, sfm_end, bwe_seed, coeff_fine );
}
/*----------------------------------------------------------------*
* Apply envelope
*----------------------------------------------------------------*/
test();
IF ( sub(HQ_mode, HQ_HARMONIC) != 0 && sub(HQ_mode, HQ_HVQ) != 0 )
{
apply_envelope_fx( coeff, norm, norm_adj, num_sfm, last_sfm, HQ_mode, length, sfm_start, sfm_end,
L_normq_v, L_coeff_out, coeff_fine, L_coeff_out1 );
}
/*----------------------------------------------------------------*
* Harmonic BWE, HVQ BWE and HQ SWB BWE
*----------------------------------------------------------------*/
test();
IF ( sub(HQ_mode, HQ_HARMONIC) == 0 )
{
harm_bwe_fx( coeff_fine, coeff, num_sfm, sfm_start, sfm_end, last_sfm, R, prev_hq_mode, norm, noise_level, prev_noise_level, bwe_seed, L_coeff_out );
}
ELSE IF ( sub(HQ_mode, HQ_HVQ) == 0 )
{
hvq_bwe_fx( L_coeff_out, coeff_fine, sfm_start, sfm_end, sfmsize, last_sfm,
prev_hq_mode, bwe_peaks, bin_th, num_sfm, L_core_brate, R, norm,
noise_level, prev_noise_level, bwe_seed, L_coeff_out, 15, 12 );
}
ELSE IF ( sub(HQ_mode, HQ_GEN_SWB) == 0 || sub(HQ_mode, HQ_GEN_FB) == 0 )
{
hq_bwe_fx( HQ_mode, L_coeff_out1, hq_generic_fenv, L_coeff_out, hq_generic_offset, prev_L_swb_norm, hq_generic_exc_clas, sfm_end, num_sfm, num_env_bands, R );
}
/*----------------------------------------------------------------*
* HQ WB BWE refinements
*----------------------------------------------------------------*/
test();
IF ( sub(length, L_FRAME16k) == 0 && L_sub(L_core_brate, HQ_32k) == 0 )
{
hq_wb_nf_bwe_fx( coeff, is_transient, prev_bfi, L_normq_v, num_sfm, sfm_start, sfm_end, sfmsize, last_sfm, R,
prev_is_transient, prev_normq, prev_env, bwe_seed, prev_coeff_out, prev_R, L_coeff_out, prev_env_Q );
}
/*----------------------------------------------------------------*
* Update memories
*----------------------------------------------------------------*/
test();
IF ( sub(HQ_mode, HQ_HARMONIC) != 0 && sub(HQ_mode, HQ_HVQ) != 0 )
{
prev_noise_level[0] = 3277;
move16();/* 0.1 in Q15 */
prev_noise_level[1] = 3277;
move16();/* 0.1 in Q15 */
}
test();
IF ( !(sub(length, L_FRAME16k) == 0 && L_sub(L_core_brate, HQ_32k) == 0) )
{
set32_fx( prev_env, 0, SFM_N_WB );
set32_fx( prev_normq, 0, SFM_N_WB );
}
test();
IF ( sub(length, L_FRAME32k) == 0 && L_sub(L_core_brate, HQ_32k) <= 0 )
{
*prev_R = R[SFM_N_WB-1];
Copy32( L_coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE );
}
return;
}
+117
View File
@@ -0,0 +1,117 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*----------------------------------------------------------------------------------*
* findpulse()
*
* Find first pitch pulse in a frame
*----------------------------------------------------------------------------------*/
Word16 findpulse_fx( /* o : pulse position */
const Word16 L_frame, /* i : length of the frame */
const Word16 res[], /* i : Residual signal <12 bits */
const Word16 T0, /* i : Pitch estimation Q0 */
const Word16 enc, /* i : enc = 1 -> encoder side; enc = 0 -> decoder side */
Word16 *sign /* i/o: sign of the maximum */
)
{
const Word16 *ptr;
Word16 maxval;
Word16 i, maxi;
Word32 Ltmp;
Word16 resf[L_FRAME16k]; /* Low pass filtered residual */
IF (enc != DEC)
{
/*------------------------------------------------------------------------*
* 1. Very simple LP filter
*------------------------------------------------------------------------*/
/* resf[0] = 0.50f * res[0] + 0.25f * res[1] */
Ltmp = L_mult(res[0], 16384);
resf[0] = mac_r(Ltmp, res[1], 8192);
move16();
FOR (i=1; i<L_frame-1; i++)
{
/* resf[i] = 0.25f * res[i-1] + 0.5f * res[i] + 0.25f * res[i+1] */
Ltmp = L_mult(8192, res[i-1]);
Ltmp = L_mac(Ltmp, 16384, res[i]);
resf[i] = mac_r(Ltmp, 8192, res[i+1]);
move16();
}
/* resf[L_frame-1] = 0.25f * res[L_frame-2] + 0.50f * res[L_frame-1] */
Ltmp = L_mult(res[L_frame-2], 8192);
resf[L_frame-1] = mac_r(Ltmp, 16384, res[L_frame-1]);
move16();
/*------------------------------------------------------------------------*
* 2. Find "biggest" pitch pulse
*------------------------------------------------------------------------*/
ptr = resf + L_frame - 1;
move16();
maxi = 0;
move16();
FOR (i = 1; i < T0; i++)
{
Ltmp = L_mult0(ptr[-maxi], ptr[-maxi]);
if (L_msu0(Ltmp, ptr[-i], ptr[-i]) < 0)
{
maxi = i;
move16();
}
}
/*
*sign = 1; move16();
test();
if (ptr[-maxi] >= 0)
{
*sign = 0; move16();
}*/
*sign = negate(shr(ptr[-maxi], 15));
move16();
}
ELSE
{
/*-----------------------------------------------------------------*
* 2. Find "biggest" pulse in the last pitch section according to the sign
*-----------------------------------------------------------------*/
maxval = 0;
move16();
maxi = 0;
move16();
IF (*sign == 0)
{
FOR (i = 0; i < T0; i++)
{
if (sub(res[i], maxval) >= 0)
{
maxi = add(i, 1);
}
maxval = s_max(res[i], maxval);
}
}
ELSE
{
FOR (i = 0; i < T0; i++)
{
if (sub(res[i], maxval) <= 0)
{
maxi = add(i, 1);
}
maxval = s_min(res[i], maxval);
}
}
}
return maxi;
}
+107
View File
@@ -0,0 +1,107 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
/*--------------------------------------------------------------------------
* subband_gain_bits()
*
* HQ core encoder
*--------------------------------------------------------------------------*/
void subband_gain_bits_fx(
const Word16 *Rk, /* i : bit allocation per band Q3 */
const Word16 N, /* i : number of bands */
Word16 *bits, /* o : gain bits per band */
const Word16 *sfmsize /* i : Size of bands */
)
{
Word16 i,b,tot;
Word16 bps;
tot = 0;
move16();
FOR ( i = 0; i < N; i++ )
{
/*bps = (short)(Rk[i]*((word16)min(32767, ceil(32767.0f/sfmsize[i]); inexact C-integer division approx. */
bps = extract_l(L_shr(L_mult0(Rk[i], inv_tbl_fx[sfmsize[i]]), 18)); /* 3+15 */
if (L_sub(L_shl(L_mult0(sfmsize[i], add(bps, 1)), 3), Rk[i]) == 0)
{
bps = add(bps, 1);
}
bps = s_min(7, bps);
b = fine_gain_bits[bps];
move16();
bits[i] = b;
move16();
tot = add(tot, b);
}
if ( tot == 0)
{
/* If no gain bits were assigned, use one bit anyway for potential PVQ overage */
bits[0] = 1;
move16();
}
return;
}
/*--------------------------------------------------------------------------*
* assign_gain_bits()
*
* Assign gain adjustment bits and update bit budget
*--------------------------------------------------------------------------*/
Word16 assign_gain_bits_fx( /* o : Number of assigned gain bits */
const Word16 core, /* i : HQ core */
const Word16 BANDS, /* i : Number of bands */
const Word16 *band_width, /* i : Sub band bandwidth */
Word16 *Rk, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */
Word16 *gain_bits_array, /* o : Assigned gain bits */
Word16 *Rcalc /* o : Bit budget for shape quantizer Q3 */
)
{
Word16 subband_cnt;
Word16 gain_bits_tot;
Word16 i;
/* Allocate gain bits for every subband used, based on bit rate and bandwidth */
IF( sub(core, HQ_CORE) == 0 )
{
subband_gain_bits_fx(Rk, BANDS, gain_bits_array, band_width);
}
ELSE
{
set16_fx( gain_bits_array, 0, BANDS );
}
/* Re-adjust bit budget for gain quantization */
subband_cnt = 0;
move16();
gain_bits_tot = 0;
move16();
*Rcalc = 0;
move16();
FOR (i = 0; i < BANDS; i++)
{
IF (Rk[i] > 0)
{
subband_cnt = add(subband_cnt, 1);
Rk[i] = sub(Rk[i], shl(gain_bits_array[i], 3));
move16();
gain_bits_tot = add(gain_bits_tot, gain_bits_array[i]);
*Rcalc = add(*Rcalc, Rk[i]);
move16();
}
}
return gain_bits_tot;
}
+196
View File
@@ -0,0 +1,196 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*----------------------------------------------------------------------------------*
* frame_ener()
*
* Estimation of pitch-synchronous (voiced) or mean half-frame (unvoiced) energy
*----------------------------------------------------------------------------------*/
Word16 frame_ener_fx(
const Word16 L_frame, /* i : length of the frame */
const Word16 clas, /* i : frame classification */
const Word16 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q_new */
const Word16 pitch, /* i : pitch period Q0 */
Word32 *enr_q, /* o : pitch-synchronous or half_frame energy Q0 */
const Word16 offset, /* i : speech pointer offset (0 or L_FRAME) */
const Word16 Q_new, /* i : Scaling factor */
Word16 shift, /* i : Shift need to obtain 12 bits vectors */
const Word16 enc /* i : Encoder/decoder */
)
{
Word16 len, exp_enrq, exp_tmp, pos;
Word16 i;
const Word16 *pt_synth;
Word32 Ltmp;
exp_enrq = 0;
move16();
test();
test();
IF( (sub(clas, VOICED_CLAS) == 0) || (sub(clas, ONSET) == 0) || (sub(clas, SIN_ONSET) == 0) ) /* current frame is voiced */
{
/* current frame is voiced */
len = pitch;
move16(); /* pitch value at the end of frame */
pt_synth = synth;
move16();
if (offset != 0)
{
pt_synth = synth + sub(L_frame, len);
}
emaximum_fx(Q_new, pt_synth, len, enr_q);
move16();/* pitch synchronous E */
IF (enc != 0)
{
exp_enrq = norm_l(*enr_q);
*enr_q = L_shl(*enr_q, exp_enrq);
move32();
exp_enrq = sub(exp_enrq, 2);
}
}
ELSE
{
/* current frame is unvoiced */
Word16 L_frame2, exp2, enr_q_tmp;
L_frame2 = shr(L_frame,1);
pos = 0;
move16();
if (offset != 0)
{
pos = sub(L_frame, L_frame2);
}
Ltmp = L_mult(synth[pos], synth[pos]);
FOR (i = 1; i < L_frame2; i++)
{
Ltmp = L_mac(Ltmp, synth[pos+i], synth[pos+i]);
}
test();
IF (L_sub(Ltmp, MAX_32) == 0 || enc != 0)
{
/* scale down when overflow occurs */
*enr_q = Energy_scale(synth+pos, L_frame2, shift, &exp_enrq);
move32();
}
ELSE
{
shift = 0;
move16();
/* Normalize acc in Q31 (energy already calculated) */
pos = norm_l(Ltmp);
Ltmp = L_shl(Ltmp, pos);
exp_enrq = sub(30, pos); /* exponent = 0..30 */
*enr_q = Ltmp;
move32();
}
/* enr2 = 1.0f/L_FRAME2 * dot_product(synth, synth, L_FRAME2) */
exp_enrq = sub(exp_enrq, shl(shift, 1));
IF (enc != 0)
{
assert(L_frame == 256 || L_frame == 320);
exp_tmp = add(shl(Q_new, 1), -2+7); /* L_subfr == L_SUBFR */
exp_enrq = sub(exp_enrq, exp_tmp);
exp_enrq = sub(31, exp_enrq);
IF(sub(L_frame, 320) == 0)
{
*enr_q = Mult_32_16(*enr_q, 26214); /*x 0.8 to get /160*/
i = norm_l(*enr_q);
*enr_q = L_shl(*enr_q, i);
exp_enrq = add(i, exp_enrq);
}
}
ELSE
{
exp_enrq = sub(exp_enrq, add(Q_new, Q_new));
enr_q_tmp /*Q30 exp2+exp_enrq*/ = BASOP_Util_Divide3216_Scale(*enr_q /*Q31*/, L_frame2 /*Q0*/, &exp2);
*enr_q = L_shr(L_deposit_l(enr_q_tmp),sub(30,add(exp2,exp_enrq))); /*Q0*/
*enr_q = L_add(*enr_q, 1);
move32();
exp_enrq = 0;
move16();
}
}
return exp_enrq;
}
/*------------------------------------------------------------------------*
* frame_energy()
*
* Compute pitch-synchronous energy at the frame end
*------------------------------------------------------------------------*/
Word16 frame_energy_fx( /* o : Frame energy in Q8 */
Word16 L_frame,
const Word16 *pitch, /* i : pitch values for each subframe Q6 */
const Word16 *speech, /* i : pointer to speech signal for E computation Q_syn*/
const Word16 lp_speech, /* i : long term active speech energy average Q8 */
Word16 *frame_ener, /* o : pitch-synchronous energy at frame end Q8 */
const Word16 Q_syn /* i : Synthesis scaling */
)
{
Word32 Ltmp;
const Word16 *pt1;
Word16 tmp16, exp1, exp2, tmp1, tmp2;
Word16 len, enern;
/* len = (0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f) */
len = mult_r(add(pitch[2], pitch[3]), 256);
if(sub(len,L_SUBFR) < 0 )
{
len = shl(len, 1);
}
pt1 = speech + sub(L_frame,len);
/* *frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len) */
tmp1 = norm_s(len);
tmp2 = shl(len, tmp1);
tmp1 = sub(15, tmp1);
Ltmp = Dot_productSq16HQ( 0, pt1, len, &exp1);
exp1 = sub(exp1, shl(Q_syn, 1));
exp1 = sub(exp1, 1); /* compensation of leftshift caused by mac operation in dot_productSq16HQ */
tmp16 = BASOP_Util_Divide3216_Scale( Ltmp, len, &exp2);
exp1 = add(exp1, exp2);
exp1 = add(exp1, 1); /* compensate result of division Q-1 */
tmp2 = norm_s(tmp16);
Ltmp = L_shl(L_deposit_h(tmp16),tmp2); /*Q16, (exp1-tmp2) = Q31, exp1-tmp2+15*/
Ltmp = BASOP_Util_Log2(Ltmp);/*Q(31-6) = Q25*/
exp1 = sub(15+exp1,tmp2);
/*add ld(2^exp1)=exp1 but check format, first*/
tmp16=sub(sub(15,norm_s(exp1)),5); /*factor to shift Ltmp and exp1 with (shr) to avoid overflows when adding*/
Ltmp= L_shr(Ltmp,tmp16); /*Q25, tmp16*/
exp2 = shr(exp1,tmp16); /*Q0 , tmp16*/
Ltmp = L_add(Ltmp,L_shl(L_deposit_l(exp2),25)); /*Q25, tmp16, normalized*/
/*make 10*log10 out of log2*/
Ltmp = Mpy_32_16_1(Ltmp,LG10); /*Q25,tmp16 * Q13 = Q23, tmp16*/
*frame_ener = extract_h(L_shl(Ltmp,add(tmp16,1)));/*Q8*/ move16();
enern = sub( *frame_ener ,lp_speech); /*Q8*/
return enern;
}
+254
View File
@@ -0,0 +1,254 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <stdint.h>
#else
#include <Winsock2.h>
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned __int64 uint64_t;
typedef signed __int64 int64_t;
#endif
#include "options.h"
#include "stl.h"
#include "g192.h"
#ifdef _MSC_VER
#pragma warning( disable : 4996 )
#endif
#define G192_SYNC_GOOD_FRAME (Word16)0x6B21
#define G192_SYNC_BAD_FRAME (Word16)0x6B20
#define G192_BIT0 (Word16)0x007F
#define G192_BIT1 (Word16)0x0081
#define MAX_BITS_PER_FRAME 2560
#define RTP_HEADER_PART1 (Word16)22 /* magic number by network simulator */
/*
* Structures
*/
/* main handle */
struct __G192
{
FILE * file;
};
/*
* Functions
*/
G192_ERROR
G192_Reader_Open(G192_HANDLE* phG192, FILE * filename)
{
/* create handle */
*phG192 = (G192_HANDLE) calloc(1, sizeof(struct __G192) );
if ( *phG192 == NULL )
{
return G192_MEMORY_ERROR;
}
memset(*phG192, 0, sizeof(struct __G192));
/* associate file stream */
(*phG192)->file = filename;
if( (*phG192)->file == NULL )
{
G192_Reader_Close(phG192);
return G192_FILE_NOT_FOUND;
}
return G192_NO_ERROR;
}
G192_ERROR
G192_ReadVoipFrame_compact(G192_HANDLE const hG192,
unsigned char * const serial,
Word16 * const num_bits,
Word16 *rtpSequenceNumber,
Word32 *rtpTimeStamp,
Word32 *rcvTime_ms)
{
Word16 short_serial [MAX_BITS_PER_FRAME];
G192_ERROR err;
Word16 i;
err = G192_ReadVoipFrame_short(hG192, short_serial, num_bits, rtpSequenceNumber, rtpTimeStamp, rcvTime_ms);
if(err != G192_NO_ERROR)
{
return err;
}
for(i=0; i<*num_bits; i++)
{
unsigned char bit = (short_serial[i] == G192_BIT1) ? 1 : 0;
unsigned char bitinbyte = bit << (7- (i&0x7));
if(!(i&0x7))
serial[i>>3] = 0;
serial[i>>3] |= bitinbyte;
}
return G192_NO_ERROR;
}
G192_ERROR
G192_ReadVoipFrame_short(G192_HANDLE const hG192,
Word16 * const serial,
Word16 *num_bits,
Word16 *rtpSequenceNumber,
Word32 *rtpTimeStamp,
Word32 *rcvTime_ms)
{
Word32 rtpPacketSize;
Word16 rtpPacketHeaderPart1;
Word32 ssrc;
Word16 rtpPayloadG192[2];
Word16 rtpPayloadSize;
/* RTP packet size */
if(fread(&rtpPacketSize, sizeof(rtpPacketSize), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "RTP Packet Size could't be read\n");
return G192_READ_ERROR;
}
if(rtpPacketSize <= 12)
{
fprintf(stderr, "RTP Packet size too small: %d\n", rtpPacketSize);
return G192_INVALID_DATA;
}
/* RTP packet arrival time */
if(fread(rcvTime_ms, sizeof(*rcvTime_ms), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "Reception Time in ms could't be read\n");
return G192_READ_ERROR;
}
/* RTP packet header (part without sequence number) */
if(fread(&rtpPacketHeaderPart1, sizeof(rtpPacketHeaderPart1), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "RTP Header couldn't be read\n");
return G192_READ_ERROR;
}
if(rtpPacketHeaderPart1 != RTP_HEADER_PART1)
{
fprintf(stderr, "Unexpected RTP Packet header\n");
return G192_INVALID_DATA;
}
/* RTP sequence number */
if(fread(rtpSequenceNumber, sizeof(*rtpSequenceNumber), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "RTP Sequence Number be read\n");
return G192_READ_ERROR;
}
*rtpSequenceNumber = ntohs(*rtpSequenceNumber);
/* RTP timestamp */
if(fread(rtpTimeStamp, sizeof(*rtpTimeStamp), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "RTP Timestamp could't be read\n");
return G192_READ_ERROR;
}
*rtpTimeStamp = ntohl(*rtpTimeStamp);
/* RTP ssrc */
if(fread(&ssrc, sizeof(ssrc), 1, hG192->file) != 1)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "RTP SSRC could't be read\n");
return G192_READ_ERROR;
}
/* RTP payload size */
rtpPayloadSize = (Word16)(rtpPacketSize - 12);
if(rtpPayloadSize <= 2)
{
fprintf(stderr, "RTP payload size too small: %d\n", rtpPayloadSize);
return G192_INVALID_DATA;
}
/* RTP payload */
if(fread(rtpPayloadG192, sizeof(Word16), 2, hG192->file) != 2)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "Premature end of file, cannot read G.192 header\n");
return G192_READ_ERROR;
}
if(rtpPayloadG192[0] != G192_SYNC_GOOD_FRAME)
{
fprintf(stderr, "G192_SYNC_WORD missing from RTP payload!");
return G192_INVALID_DATA;
}
*num_bits = rtpPayloadG192[1];
if(*num_bits == 0 || *num_bits + 2 != rtpPayloadSize || *num_bits > MAX_BITS_PER_FRAME)
{
fprintf(stderr, "error in parsing RTP payload: rtpPayloadSize=%u nBits=%d",
rtpPayloadSize, *num_bits);
return G192_INVALID_DATA;
}
if( (Word16)fread(serial, sizeof(Word16), *num_bits, hG192->file) != *num_bits)
{
if(feof( hG192->file) != 0)
{
return G192_EOF;
}
fprintf(stderr, "Premature end of file, cannot read G.192 payload\n");
return G192_READ_ERROR;
}
return G192_NO_ERROR;
}
G192_ERROR
G192_Reader_Close(G192_HANDLE* phG192)
{
if(phG192 == NULL || *phG192 == NULL)
{
return G192_NO_ERROR;
}
free( *phG192 );
*phG192 = NULL;
phG192 = NULL;
return G192_NO_ERROR;
}
+64
View File
@@ -0,0 +1,64 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef G192_H
#define G192_H G192_H
/*
* ENUMS
*/
/* error enums */
typedef enum _G192_ERROR
{
G192_NO_ERROR = 0x0000,
G192_MEMORY_ERROR = 0x0001,
G192_WRONG_PARAMS = 0x0002,
G192_INIT_ERROR = 0x0003,
G192_WRITE_ERROR = 0x0004,
G192_READ_ERROR = 0x0005,
G192_FILE_NOT_FOUND = 0x0006,
G192_INVALID_DATA = 0x0007, /* error returned when read data is invalid */
G192_NOT_IMPLEMENTED = 0x0010,
G192_NOT_INITIALIZED = 0x0100,
G192_UNKNOWN_ERROR = 0x1000,
G192_EOF = 0xffff /* EOF during reading */
} G192_ERROR;
/*
* Structures
*/
/* main handle */
struct __G192;
typedef struct __G192 * G192_HANDLE;
/*
* Functions
*/
G192_ERROR
G192_Reader_Open(G192_HANDLE* phG192, FILE * filename);
G192_ERROR
G192_ReadVoipFrame_compact(G192_HANDLE const hG192,
unsigned char * const serial,
Word16 * const num_bits,
Word16 *rtpSequenceNumber,
Word32 *rtpTimeStamp,
Word32 *rcvTime_ms);
G192_ERROR
G192_ReadVoipFrame_short(G192_HANDLE const hG192,
Word16 * const serial,
Word16 *num_bits,
Word16 *rtpSequenceNumber,
Word32 *rtpTimeStamp,
Word32 *rcvTime_ms);
G192_ERROR
G192_Reader_Close(G192_HANDLE* phG192);
#endif /* G192_H */
+54
View File
@@ -0,0 +1,54 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "prot_fx.h"
#include "stl.h"
#include "basop_util.h"
#include "rom_com_fx.h"
Word32 calc_gain_inov( /* returns innovation gain Q16 */
const Word16 *code, /* i : algebraic excitation Q9 */
Word16 lcode, /* i : Subframe size Q0 */
Word32 *dotp, /* o : intermediate result Q31-e */
Word16 *dotp_e /* o : intermediate result exponent Q0 */
)
{
Word32 L_tmp;
Word16 exp_L_tmp, i;
/* L_tmp = dot_product(code, code, lcode) + 0.01 */
L_tmp = Dot_product12_offs(code, code, lcode, &exp_L_tmp, 2621l/*0.01f/2.0f Q19*/);
exp_L_tmp = sub(exp_L_tmp, 18);
/* gain_inov = 1.0f / sqrt((dot_product(code, code, lcode) + 0.01) / lcode) */
/* Note: lcode is in range: 32,40,64,80 */
assert((lcode == 32) || (lcode == 40) || (lcode == 64) || (lcode == 80));
if (s_and(lcode, sub(lcode, 1)) != 0)
{
L_tmp = Mpy_32_32(L_tmp, 1717986918l/*64.0/80.0 Q31*/);
}
exp_L_tmp = sub(exp_L_tmp, sub(14, norm_s(lcode)));
i = norm_l(L_tmp);
L_tmp = L_shl(L_tmp, i);
exp_L_tmp = sub(exp_L_tmp, i);
if (dotp != NULL)
{
*dotp = L_tmp;
move32();
}
if (dotp_e != NULL)
{
*dotp_e = exp_L_tmp;
move16();
}
L_tmp = ISqrt32norm(L_tmp, &exp_L_tmp);
return L_shl(L_tmp, sub(exp_L_tmp, 15)); /* 15Q16 */
}
+97
View File
@@ -0,0 +1,97 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "prot_fx.h"
#include "stl.h"
#include "basop_util.h"
Word32 get_gain( /* output: codebook gain (adaptive or fixed) Q16 */
Word16 x[], /* input : target signal */
Word16 y[], /* input : filtered codebook excitation */
Word16 n /* input : segment length */
)
{
Word32 tcorr, tener, Lgain;
Word16 exp_c, exp_e, exp, tmp;
tcorr = L_deposit_l(0);
tener = L_deposit_l(0);
/*----------------------------------------------------------------*
* Find gain based on inter-correlation product
*----------------------------------------------------------------*/
tcorr = Dot_product16HQ( 0, x, y, n, &exp_c );
tener = Dot_productSq16HQ( 0, y, n, &exp_e );
BASOP_Util_Divide_MantExp(round_fx(tcorr), exp_c, s_max(round_fx(tener),1), exp_e, &tmp,&exp);
Lgain = L_shl(L_deposit_l(tmp)/*Q15*/,add(1,exp))/*Q16*/;
return Lgain;
}
Word32 get_gain2( /* output: codebook gain (adaptive or fixed) Q16 */
Word16 x[], /* input : target signal */
Word16 y[], /* input : filtered codebook excitation */
Word16 n /* input : segment length */
)
{
Word32 tcorr, tener, Lgain;
Word16 m_corr, m_ener, negative, Q_corr, Q_ener;
negative = 0;
move16();
/*----------------------------------------------------------------*
* Find gain based on inter-correlation product
*----------------------------------------------------------------*/
tcorr = Dot_product16HQ(0, x, y, n, &Q_corr);
tener = Dot_productSq16HQ(0, y, n, &Q_ener);
tener = L_max(tener, 1);
if (tcorr <= 0)
{
negative = 1;
move16();
}
BASOP_SATURATE_WARNING_OFF /*tcorr max be negative maxvall - not critical*/
tcorr = L_abs(tcorr);
BASOP_SATURATE_WARNING_ON
m_corr = extract_h(tcorr);
m_ener = extract_h(tener);
IF (sub(m_corr, m_ener) > 0)
{
m_corr = shr(m_corr, 1);
Q_corr = add(Q_corr,1);
}
if (m_ener==0)
{
move16();
m_corr = 0x7FFF;
}
if (m_ener != 0)
{
m_corr = div_s(m_corr, m_ener);
}
Q_corr = sub(Q_corr,Q_ener);
Lgain = L_shl(L_deposit_l(m_corr), add(Q_corr, 1)); /* Lgain in Q16 */
if (negative != 0)
{
Lgain = L_negate(Lgain); /* Lgain in Q16 */
}
return Lgain;
}
+481
View File
@@ -0,0 +1,481 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "assert.h" /* Debug prototypes */
#include "stl.h"
/*==================================================================================*/
/* FUNCTION : void bands_and_bit_alloc_fx(); */
/*----------------------------------------------------------------------------------*/
/* PURPOSE : AC mode (GSC) bands and bits allocation */
/*----------------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) cor_strong_limit : HF correlation */
/* _ (Word16) noise_lev : dwn scaling factor Q0 */
/* _ (Word32) core_brate : core codec used Q0 */
/* _ (Word16) Diff_len : Lenght of the difference signal Q0 */
/* _ (Word16) bits_used : Number of bit used before frequency Q0 */
/* _ (Word16) idx : Energy band 14 Q0 */
/* _ (Word16*) exc_diff : Difference signal to quantize (Encoder only) */
/* _ (Word16) coder_type : coding type Q0 */
/* _ (Word16) bwidth : input signal bandwidth Q0 */
/*----------------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) max_ener_band : Sorted order */
/* _ (Word16*) nb_subbands : Number of subband allowed Q0 */
/* _ (Word16*) concat_in : Concatened PVQ's input vector (Encoder Only) */
/* _ (Word16*) pvq_len : Number of bin covered with the PVQ Q0 */
/*----------------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16*) bit :Number of bit allowed for frequency quantization */
/* _ (Word16*) Ener_per_bd_iQ : Quantized energy vector Q13 */
/* _ (Word32*) bits_per_bands : Number of bit allowed per allowed subband Q18 */
/*----------------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*==================================================================================*/
void bands_and_bit_alloc_fx(
const Word16 cor_strong_limit, /* i : HF correlation */
const Word16 noise_lev, /* i : dwn scaling factor */
const Word32 core_brate, /* i : core bit rate */
const Word16 Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/
const Word16 bits_used, /* i : Number of bit used before frequency Q */
Word16 *bit, /* i/o: Number of bit allowed for frequency quantization */
const Word16 *Ener_per_bd_iQ, /* i/o: Quantized energy vector */
Word16 *max_ener_band, /* o : Sorted order */
Word16 *out_bits_per_bands, /* i/o: Number of bit allowed per allowed subband Q3 */
Word16 *nb_subbands, /* o : Number of subband allowed */
const Word16 *exc_diff, /* i : Difference signal to quantize (encoder side only) */
Word16 *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */
Word16 *pvq_len, /* o : Number of bin covered with the PVQ */
const Word16 coder_type, /* i : coding type */
const Word16 bwidth, /* i : input signal bandwidth */
const Word16 GSC_noisy_speech
)
{
Word16 bandoffset, i, j, nb_bands_max, bit_new_bands, bit_tmp, st_band, nb_bands;
Word16 ener_vec[MBANDS_GN]; /*Q12 */
Word16 nb_tot_bands = 16;
Word16 bit_index, bit_index_mem, imax;
Word32 L_tmp;
Word32 sum_bit, bit_fracf;
Word16 etmp;
Word16 tmp;
Word16 Ener_per_bd_iQ_tmp[MBANDS_GN];
Word16 pos, band;
Word16 SWB_bit_budget;
Word32 bits_per_bands[MBANDS_GN];
Word16 w_sum_bit;
Copy( Ener_per_bd_iQ, Ener_per_bd_iQ_tmp, MBANDS_GN );
set32_fx( bits_per_bands, 0, MBANDS_GN );
set16_fx( out_bits_per_bands, 0, MBANDS_GN );
/* To adapt current energy band to PVQ freq band for sorting*/
ener_vec[0] = add(Ener_per_bd_iQ[0],Ener_per_bd_iQ[1]); /*Q12 */
Copy( Ener_per_bd_iQ_tmp+1, ener_vec, 15 ); /*Q12 */
ener_vec[15] = ener_vec[14];
move16();
/*------------------------------------------------------------------------
* Determination of the number of bits available to the frequency domain
* Allocation of a maximum number of band to be encoded
*-----------------------------------------------------------------------*/
nb_bands_max = nb_tot_bands;
move16();
bit_new_bands = 5;
move16();
bit_index = i_mult2(BRATE2IDX_fx(core_brate),17);
bit_index_mem = bit_index;
move16();
test();
test();
IF( (sub(coder_type,AUDIO) == 0 || sub(coder_type,INACTIVE) == 0) && sub(bwidth,NB) == 0 )
{
IF(L_sub(core_brate,ACELP_9k60) >= 0)
{
/* *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 25; */
L_tmp = Mult_32_16(core_brate,20971);
tmp = extract_l(L_shr_r(L_tmp,5));
*bit = sub(sub(tmp,bits_used), 25);
move16();
}
ELSE
{
L_tmp = Mult_32_16(core_brate,20971);
tmp = extract_l(L_shr_r(L_tmp,5));
*bit = sub(sub(tmp,bits_used), 21);
move16();
}
nb_tot_bands = 10;
move16();
}
ELSE
{
/* *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - GSC_freq_bits[bit_index]; */
L_tmp = Mult_32_16(core_brate,20971);
tmp = extract_l(L_shr_r(L_tmp,5));
*bit = sub(sub(tmp,bits_used),GSC_freq_bits[bit_index]);
move16();
}
IF( sub(GSC_noisy_speech,1) == 0 )
{
SWB_bit_budget = *bit;
move16();
nb_bands = 5;
move16();
st_band = nb_bands;
move16();
set32_fx( bits_per_bands, 0, MBANDS_GN );
/*bit_fracf = (1.0f/nb_bands)*(SWB_bit_budget); */
bit_fracf = L_mult(div_s(1,nb_bands),shl(SWB_bit_budget,2)); /* Q18 */
nb_tot_bands = sub(nb_bands_max,6);
nb_tot_bands = s_min(nb_tot_bands, 16);
FOR(j = 0; j < 2; j++)
{
i = j;
move16();
max_ener_band[j] = i;
move16();
ener_vec[i] = 0;
move16();
}
FOR(; j < nb_bands; j++)
{
i = maximum_fx(ener_vec, nb_tot_bands, &etmp);
max_ener_band[j] = i;
move16();
ener_vec[i] = 0;
move16();
}
set32_fx(bits_per_bands, bit_fracf, nb_bands);
}
ELSE
{
bit_index++;
bit_tmp = sub(*bit,GSC_freq_bits[bit_index]);
bit_index++;
nb_bands_max = add(nb_bands_max,GSC_freq_bits[bit_index]);
bit_index++;
*pvq_len = 112;
move16();
st_band = 7;
move16();
IF( L_sub(core_brate,ACELP_9k60) <= 0 )
{
*pvq_len = 80;
move16();
st_band = 5;
move16();
IF( Diff_len == 0 )
{
nb_bands_max = add(nb_bands_max,2);
bit_tmp = sub(bit_tmp,13);
}
}
ELSE IF( Diff_len == 0 )
{
nb_bands_max = add(nb_bands_max,2);
bit_tmp = sub(bit_tmp,17);
}
nb_bands = shr(*pvq_len,4);
/*------------------------------------------------------------------------
* Ajustement of the maximum number of bands in function of the
* dynamics of the spectrum (more or less speech like)
*-----------------------------------------------------------------------*/
test();
test();
test();
test();
IF( sub(coder_type,INACTIVE) == 0 || sub(noise_lev,NOISE_LEVEL_SP3) >= 0 )
{
/* Probably classification error -> concentrate bits on LF */
nb_bands_max = nb_bands;
move16();
if( L_sub(core_brate,ACELP_8k00) >= 0 )
{
nb_bands_max = add(nb_bands,1);
}
}
ELSE IF( sub(noise_lev,NOISE_LEVEL_SP2) >= 0 ||
(L_sub(core_brate,ACELP_13k20) <= 0 && L_sub(core_brate,ACELP_9k60) >= 0 && cor_strong_limit == 0) ) /* Very low dynamic, tend to speech, do not try to code HF at all */
{
nb_bands_max = sub(nb_bands_max,2);
}
ELSE if( sub(noise_lev,NOISE_LEVEL_SP1) >= 0) /* Very low dynamic, tend to speech, code less HF */
{
nb_bands_max = sub(nb_bands_max,1);
}
test();
if( sub(bwidth,NB) == 0 && sub(nb_bands_max,10) > 0 )
{
nb_bands_max = 10;
move16();
}
/*------------------------------------------------------------------------
* Find extra number of band to code according to bit rate availables
*-----------------------------------------------------------------------*/
WHILE ( sub(bit_tmp,bit_new_bands) >= 0 && sub(nb_bands,sub(nb_bands_max, 1)) <= 0 )
{
bit_tmp = sub(bit_tmp,bit_new_bands);
nb_bands = add(nb_bands,1);
}
/*------------------------------------------------------------------------
* Fractional bits to distribute on the first x bands
*-----------------------------------------------------------------------*/
bit_fracf = L_mult(div_s(1,st_band),shl(bit_tmp,2)); /* Q18 */
/*------------------------------------------------------------------------
* Complete the bit allocation per frequency band
*-----------------------------------------------------------------------*/
imax = 5;
move16();
if( L_sub(core_brate,ACELP_9k60) > 0 )
{
imax = 7;
move16();
}
FOR(i = 0; i < imax; i++)
{
bits_per_bands[i] = L_add(GSC_freq_bits_fx[bit_index],bit_fracf);
move32();/* Q18 */
bit_index = add(bit_index,1);
}
IF( Diff_len == 0 )
{
bit_index = add(bit_index_mem,10);
FOR( i = 0; i < 7; i++ )
{
bits_per_bands[i] = L_add(bits_per_bands[i],GSC_freq_bits_fx[bit_index]);
move32();/*chk Q18 */
bit_index = add(bit_index,1);
}
}
/*--------------------------------------------------------------------------
* Complete the bit allocation per frequency band for 16kHz high brate mode
*--------------------------------------------------------------------------*/
FOR( j = st_band; j < nb_bands; j++ )
{
bits_per_bands[j] = L_shl(bit_new_bands,18);
move32(); /*chk Q18 */
}
/*--------------------------------------------------------------------------
* Compute a maximum band (band offset) for the search on maximal energy
* This is function of the spectral dynamic and the bitrate
*--------------------------------------------------------------------------*/
bandoffset = sub(nb_tot_bands,add(nb_bands,2));
test();
test();
test();
test();
test();
IF( sub(noise_lev,NOISE_LEVEL_SP1a) <= 0 )
{
bandoffset = sub(bandoffset,1);
}
ELSE if ( (L_sub(core_brate,ACELP_13k20) <= 0 && (sub(coder_type,INACTIVE) == 0 || sub(noise_lev,NOISE_LEVEL_SP3) >= 0)) ||
(L_sub(core_brate,ACELP_13k20) <= 0 && L_sub(core_brate,ACELP_9k60) >= 0 && cor_strong_limit == 0) )
{
bandoffset = add(bandoffset,1);
}
bandoffset = s_max(bandoffset ,0);
/*--------------------------------------------------------------------------
* Initiazed sorted vector
* For the first x bands to be included in th final sorted vector
* Sort the remaining bands in decrease energy order
*--------------------------------------------------------------------------*/
FOR(j = 0; j < nb_tot_bands; j++)
{
max_ener_band[j] = -10;
move16();
}
FOR(j = 0; j < st_band; j++)
{
max_ener_band[j] = j;
move16();
ener_vec[j] = -10;
move16();
}
pos = st_band;
move16();
FOR(; j < nb_bands; j++)
{
i = maximum_fx(ener_vec, sub(nb_tot_bands,bandoffset), &etmp);
pos = s_max(pos,i);
max_ener_band[j] = i;
move16();
ener_vec[i] = -10;
move16();
}
/* re-allocate bits to the frames such that the highest band with allocated bits is higher than the threshold */
test();
test();
test();
IF( sub(sub(nb_tot_bands, bandoffset),nb_bands) > 0 && ( sub(pos,7) > 0 && L_sub(core_brate,ACELP_8k00) == 0 ) && sub(bwidth,WB) == 0 )
{
band = sub(nb_tot_bands, add(bandoffset,nb_bands));
FOR(j=0; j<band; j++)
{
i = maximum_fx( ener_vec, sub(nb_tot_bands,bandoffset), &etmp );
max_ener_band[add(nb_bands,j)] = i;
move16();
ener_vec[i] = -10;
move16();
bits_per_bands[add(nb_bands,j)] = 1310720;
move32(); /*Q18 */
}
nb_bands = add(nb_bands,band);
bit_tmp = i_mult2(band,5);
IF( sub(band,2) <= 0 )
{
FOR(j = sub(st_band,1); j < nb_bands; j++)
{
bits_per_bands[j] = L_add(bits_per_bands[j],262144); /*Q18 */ move32();
}
bit_tmp = add(bit_tmp, add(sub(nb_bands, st_band) , 1));
}
i = 0;
move16();
j = 0;
move16();
FOR( ; bit_tmp > 0; bit_tmp--)
{
bits_per_bands[j] = L_sub(bits_per_bands[j],262144); /*Q18 */
j = add(j,1);
if ( sub(j,sub(st_band, i)) == 0 )
{
j = 0;
move16();
}
test();
if( j == 0 && sub(i,sub(st_band, 1)) < 0)
{
i = add(i,1);
}
}
}
}
/*--------------------------------------------------------------------------
* Bit sum verification for GSC inactive at very high rate
* The maximum number of bits per band of length 16 is 112
* Redistribute the overage bits if needed
*--------------------------------------------------------------------------*/
sum_bit = 0;
move16();
j = 0;
move16();
FOR( i = 0; i < nb_bands; i++ )
{
L_tmp = Mult_32_16(sum_bit,10923);
IF( L_sub(bits_per_bands[i],29360128) > 0) /* 112 in Q18 */
{
sum_bit = L_add(sum_bit,L_sub(bits_per_bands[i],29360128)); /* Q18 */
bits_per_bands[i] = 29360128;
move32();
j = add(i,1);
}
ELSE if( L_sub(L_add(bits_per_bands[i],L_tmp),29360128 ) > 0) /* Q18 */
{
j = add(i,1);
}
}
IF( sum_bit != 0 )
{
tmp = sub(nb_bands,j);
sum_bit = Mult_32_16(sum_bit,div_s(1,tmp)); /* Q18 */
FOR( i = j; i < nb_bands; i++ )
{
bits_per_bands[i] = L_add(bits_per_bands[i],sum_bit);
move32();/* Q18 */
}
}
/*--------------------------------------------------------------------------
* second step of bit sum verification, normally sum_bit == *bit
*--------------------------------------------------------------------------*/
w_sum_bit = 0;
move16();
FOR( i = 0; i < nb_bands; i++ )
{
out_bits_per_bands[i] = shl(extract_l(L_shr(bits_per_bands[i],18)),3);
move16();
w_sum_bit = add(w_sum_bit,out_bits_per_bands[i]); /* Q3 */
}
tmp = shl(*bit,3);
IF( sub(tmp,w_sum_bit)>0 )
{
i = sub(nb_bands,1);
move16();
FOR( ; tmp > w_sum_bit; w_sum_bit += (1<<3) )
{
out_bits_per_bands[i] = add(out_bits_per_bands[i],1<<3);
move16();
i = sub(i, 1);
if(i==0)
{
i = sub(nb_bands,1);
}
}
}
/*--------------------------------------------------------------------------
* Recompute the real number/length of frequency bands to encode
*--------------------------------------------------------------------------*/
*nb_subbands = nb_bands;
move16();
*pvq_len = shl(*nb_subbands,4);
/*--------------------------------------------------------------------------
* Concatenate bands (encoder only)
*--------------------------------------------------------------------------*/
IF( exc_diff != NULL )
{
FOR( j = 0; j < nb_bands; j++ )
{
Copy( exc_diff + shl(max_ener_band[j],4), concat_in+shl(j,4), 16 );
}
}
return;
}
+673
View File
@@ -0,0 +1,673 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
static Word16 VDQ_vec_fx( Word16 *Qvec_out_fx, const Word16 *mean_dic_fx, const Word16 *dic_fx,
const Word16 index_fx, const Word16 vec_en_fx );
/*========================================================================*/
/* FUNCTION : void Comp_and_apply_gain_enc_fx */
/*------------------------------------------------------------------------*/
/* PURPOSE : Compute and apply the quantized per band gain */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16[]) Ener_per_bd_iQ : Target ener per band Q12 */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16[]) exc_diffQ : Quantized excitation Qexc */
/* _ (Word16[]) Ener_per_bd_yQ : Ener per band for norm vectori->Q12/o->Q2*/
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
void Comp_and_apply_gain_fx(
Word16 exc_diffQ[], /* i/o: Quantized excitation */
Word16 Ener_per_bd_iQ[], /* i : Target ener per band Q13 */
Word16 Ener_per_bd_yQ[], /* i/o : Ener per band for norm vector i->Q13/o->Q13 */
Word16 Mbands_gn, /* i : number of bands */
const Word16 ReUseGain, /* i : Reuse the gain in Ener_per_bd_yQ */
Word16 Qexc_diff,
Word16 Q_exc
)
{
Word16 i, i_band;
Word16 StartBin, NB_Qbins;
Word16 y_gain;
Word16 L16, frac, exp1, tmp_exp;
Word32 L32;
/* Recreate excitation for local synthesis and decoder */
StartBin = 0;
move16();
NB_Qbins = 0;
move16();
tmp_exp = add(14,sub(Q_exc,Qexc_diff)); /* In case of reuse, it can be computed outside the loop*/
FOR( i_band = 0; i_band < Mbands_gn; i_band++ )
{
StartBin = add(StartBin, NB_Qbins);
NB_Qbins = mfreq_bindiv_loc[i_band];
move16();
IF( sub(ReUseGain,1) == 0 )
{
y_gain = Ener_per_bd_yQ[i_band];
move16();
FOR(i = StartBin ; i < NB_Qbins + StartBin ; i++)
{
L32 = L_shl(L_mult(exc_diffQ[i], y_gain),tmp_exp); /*Q_exc+16 */
exc_diffQ[i] = round_fx(L32);/*Q_exc */
}
}
ELSE
{
/*-----------------------------------------------------------------*
* y_gain = pow(10.0, (Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band]))
* = pow(2, 3.321928*(Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band]))
*-----------------------------------------------------------------*/
L16 = sub(Ener_per_bd_iQ[i_band], Ener_per_bd_yQ[i_band]);/*Q12 */
L32 = L_mult(L16, 27213); /* 3.321928 in Q13 -> Q26 */
L32 = L_shr(L32, 10); /* From Q26 to Q16 */
frac = L_Extract_lc(L32, &exp1); /* Extract exponent of gcode0 */
y_gain = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16384 < Pow2() <= 32767 */
Ener_per_bd_yQ[i_band] = shl(y_gain, sub(exp1, 13));
move16();/*Q1 */
tmp_exp = add(add(exp1,1),sub(Q_exc,Qexc_diff));
FOR(i = StartBin ; i < NB_Qbins + StartBin ; i++)
{
L32 = L_mult(exc_diffQ[i], y_gain); /*Qexc_diff+15 */
exc_diffQ[i] = round_fx(L_shl(L32,tmp_exp)); /*Q_exc */
}
}
}
return;
}
/*========================================================================*/
/* FUNCTION : Ener_per_band_comp_fx() */
/*------------------------------------------------------------------------*/
/* PURPOSE : Compute the energy per band in log domain for quantization */
/* purposes. */
/* Loops are decomposed to accomodate the PVQ quantization */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16*) edct_table_128_fx : edct table Q15 */
/* _ (Word16*) Q_exc_diff : input format of exc_diff */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16[]) y_gain4 : Energy per band to quantize Q12 */
/* _ (Word32*) etmp14 : Energy band 14 Q_exc_diff*2+1 */
/* _ (Word32*) etmp15 : Energy band 15 Q_exc_diff*2+1 */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
static Word16 Comp_band_log_ener( /* o : Band gain Q12 */
const Word16 *pt_fx, /* i : Dct input Q_sc */
const Word16 Len, /* i : Lenght en energy accumulation */
const Word16 Q_sc, /* i : scaling of input */
const Word16 E_sc /* i : Additional scaling factor for energy */
)
{
Word32 L_tmp;
Word16 e_tmp, f_tmp, tmp16, ener_exp;
/*for(i = 0; i < 8; i++){etmp += (*pt * *pt);pt++;}*/
L_tmp = Calc_Energy_Autoscaled(pt_fx, Q_sc, Len, &ener_exp);
/*y_gain4[j] = (float)log10(sqrt(etmp<<E_sc));*/
e_tmp = norm_l(L_tmp);
f_tmp = Log2_norm_lc(L_shl(L_tmp, e_tmp));
e_tmp = sub(sub(add(30,E_sc),e_tmp),ener_exp);
L_tmp = Mpy_32_16(e_tmp, f_tmp, 19728); /* Q16 */ /*log10(2) in Q17 */
tmp16 = round_fx(L_shl(L_tmp, 12-2)); /* Q12 -1 is to compensate Q17 */
return tmp16;
}
void Ener_per_band_comp_fx(
const Word16 exc_diff_fx[], /* i : target signal Q_exc_diff */
Word16 y_gain4_fx[], /* o : Energy per band to quantize Q12 */
const Word16 Q_exc, /* i : frame length */
const Word16 Mband, /* i : Max band */
const Word16 Eflag /* i : flag of highest band */
)
{
const Word16 *pt_fx;
Word16 j;
pt_fx = exc_diff_fx;
FOR(j = 0; j < 2; j++)
{
y_gain4_fx[j] = Comp_band_log_ener(pt_fx, 8, Q_exc, 1);
move16();
pt_fx += 8;
}
FOR(j = 1; j < Mband-2; j++)
{
y_gain4_fx[j+1] = Comp_band_log_ener(pt_fx, 16, Q_exc, 0);
move16();
pt_fx += 16;
}
IF( sub(Eflag,1) == 0 )
{
y_gain4_fx[j+1] = Comp_band_log_ener(pt_fx, 32, Q_exc, -1);
move16();
pt_fx += 32;
}
return;
}
/*-------------------------------------------------------------------*
* gsc_gainQ()
*
* Quantization of the energy per band
*-------------------------------------------------------------------*/
static void GSC_gain_adj(
const Word16 coder_type, /* i : Coder type */
const Word32 core_brate, /* i : Bit rate */
const Word16 mean_g, /* i : Average gain Q12 */
Word16 *old_y_gain, /* i/o: Previous frame dequantized vector */
const Word16 *y_gain_tmp, /* i : Dequantized gains */
Word16 *y_gainQ /* i/o: Output gains Q12 */
)
{
/* Gain adjustment to fit ACELP generic inactive coding gain at low rate */
Word16 Gain_off, i;
IF( sub(coder_type,INACTIVE) != 0 )
{
FOR( i = 0; i < MBANDS_GN; i++ )
{
old_y_gain[i] = y_gain_tmp[i];
move16();
y_gainQ[i] = add(y_gain_tmp[i], mean_g);
move16();
}
}
ELSE
{
Gain_off = 0;
move16();
IF(L_sub(core_brate,ACELP_7k20) <= 0 )
{
Gain_off = 32767;
move16(); /* 8 -> Q12 */
}
ELSE IF (L_sub(core_brate,ACELP_8k00) <= 0)
{
Gain_off = 27034;
move16(); /* 6.6f -> Q12 */
}
ELSE IF (L_sub(core_brate,ACELP_9k60) <= 0)
{
Gain_off = 19661;
move16(); /*4.8f-> Q12 */
}
ELSE IF (L_sub(core_brate,ACELP_11k60) <= 0)
{
Gain_off = 14336;
move16(); /* 3.5f -> Q12 */
}
ELSE IF (L_sub(core_brate,ACELP_13k20) <= 0)
{
Gain_off = 12288;
move16(); /* 3.0f -> Q12 dB */
}
/*mimic ACELP decay of energy for low rates*/
FOR( i = 0; i < MBANDS_GN; i++ )
{
old_y_gain[i] = y_gain_tmp[i];
move16();
/*y_gainQ[i] = y_gain_tmp[i]+mean_4g[0]-(i*(Gain_off/20.f)/((float) Mbands_gn));*/
y_gainQ[i] = add(y_gain_tmp[i], sub(mean_g, i_mult2(i, mult_r(Gain_off, 102))));
move16();
}
}
return;
}
/*==========================================================================*/
/* FUNCTION : Word16 gsc_gaindec_fx () */
/*--------------------------------------------------------------------------*/
/* PURPOSE : Generic signal frequency band decoding and application */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) pvq_bits_fx : core used Q0 */
/* _ (Word16) coder_type_fx : coding type Q0 */
/* _ (Word16) core_fx : core used Q0 */
/* _ (Word16) bwidth_fx : input signal bandwidth Q0 */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16[]) y_gainQ_fx : quantized gain per band */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16[]) old_y_gain_fx : AR gain quantizer for low rate */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ (Word16) : average frequency gain */
/*==========================================================================*/
Word16 gsc_gaindec_fx( /* o : average frequency gain */
Decoder_State_fx *st_fx, /* i/o: decoder state structure */
Word16 y_gainQ_fx[], /* o : quantized gain per band */
const Word32 core_brate_fx, /* i : core used */
Word16 old_y_gain_fx[], /* i/o: AR gain quantizer for low rate */
const Word16 coder_type_fx, /* i : coding type */
const Word16 bwidth_fx /* i : input signal bandwidth */
)
{
Word16 idx_g_fx, i;
Word16 mean_4g_fx;
Word16 y_gain_tmp3_fx[MBANDS_GN];
test();
test();
IF( (sub(coder_type_fx,AUDIO) == 0 || sub(coder_type_fx,INACTIVE) == 0) && sub(bwidth_fx,NB) == 0 )
{
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 );
VDQ_vec_fx(&mean_4g_fx, Gain_meanNB_fx, Gain_mean_dicNB_fx, idx_g_fx, 1 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 );
move16();
VDQ_vec_fx(y_gainQ_fx, Mean_dic_NB_fx, Gain_dic1_NB_fx, idx_g_fx, 3 );
IF(L_sub(core_brate_fx,ACELP_9k60) < 0)
{
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx+3, Mean_dic_NB_fx+3, Gain_dic2_NB_fx, idx_g_fx, 3 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 4 );
VDQ_vec_fx(y_gainQ_fx+6, Mean_dic_NB_fx+6, Gain_dic3_NB_fx, idx_g_fx, 4 );
}
ELSE
{
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 );
VDQ_vec_fx(y_gainQ_fx+3, Mean_dic_NB_fx+3, Gain_dic2_NBHR_fx, idx_g_fx, 3 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 7 );
VDQ_vec_fx(y_gainQ_fx+6, Mean_dic_NB_fx+6, Gain_dic3_NBHR_fx, idx_g_fx, 4 );
}
test();
IF( L_sub(core_brate_fx,ACELP_9k60) <= 0 && sub(coder_type_fx,INACTIVE) == 0 )
{
/* Some energy is needed in high band for stat_noise_uv_enc
to be functional in inactive speech */
y_gainQ_fx[10] = mean_fx(y_gainQ_fx+6, 3);
move16();
y_gainQ_fx[11] = mean_fx(y_gainQ_fx+7, 3);
move16();
y_gainQ_fx[12] = mean_fx(y_gainQ_fx+8, 3);
move16();
y_gainQ_fx[13] = mean_fx(y_gainQ_fx+9, 3);
move16();
y_gainQ_fx[14] = mean_fx(y_gainQ_fx+10, 3);
move16();
y_gainQ_fx[15] = mean_fx(y_gainQ_fx+11, 3);
move16();
}
ELSE
{
set16_fx( y_gainQ_fx + 10, 0, MBANDS_GN - 10 );
}
}
ELSE
{
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 );
VDQ_vec_fx(&mean_4g_fx, mean_m_fx, mean_gain_dic_fx, idx_g_fx, 1 );
IF(L_sub(core_brate_fx,ACELP_9k60) <= 0)
{
/*--------------------------------------------------------------------------------------*
* UQ of the first 8 bands and half of the last 8 bands
*--------------------------------------------------------------------------------------*/
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx, YGain_mean_LR_fx, YGain_dic1_LR_fx, idx_g_fx, 3 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx+3, YGain_mean_LR_fx+3, YGain_dic2_LR_fx, idx_g_fx, 4 );
/*----------------------------------------------------------------------*
* Interpolation of the last 4 Q bands to create bands 8-16
* And scaling
*----------------------------------------------------------------------*/
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx+7, YGain_mean_LR_fx+7, YGain_dic3_LR_fx, idx_g_fx, 5 );
Copy(y_gainQ_fx+8, y_gain_tmp3_fx, 4);
set16_fx(y_gainQ_fx+12, 0, 4);
fft_rel_fx(y_gainQ_fx+8, 4, 2);
y_gainQ_fx[15] = y_gainQ_fx[11];
move16();
y_gainQ_fx[11] = 0;
move16();
ifft_rel_fx(y_gainQ_fx+8, 8, 3);
FOR(i = 8; i < 16; i++)
{
/*y_gainQ_fx[i] *= 1.41f;*/
y_gainQ_fx[i] = round_fx(L_shl(L_mult(y_gainQ_fx[i] , 23101),1));/*Q12 */
}
/*----------------------------------------------------------------------*
* Copy the true Q values in the specific bands
*----------------------------------------------------------------------*/
y_gainQ_fx[8] = y_gain_tmp3_fx[0];
move16();
y_gainQ_fx[10]= y_gain_tmp3_fx[1];
move16();
y_gainQ_fx[12]= y_gain_tmp3_fx[2];
move16();
y_gainQ_fx[14]= y_gain_tmp3_fx[3];
move16();
}
ELSE
{
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 );
VDQ_vec_fx(y_gainQ_fx, YG_mean16_fx, YG_dicMR_1_fx, idx_g_fx, 4 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx+4, YG_mean16_fx+4, YG_dicMR_2_fx, idx_g_fx, 4 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 );
VDQ_vec_fx(y_gainQ_fx+8, YG_mean16_fx+8, YG_dicMR_3_fx, idx_g_fx, 4 );
idx_g_fx = (Word16) get_next_indice_fx( st_fx, 4 );
VDQ_vec_fx(y_gainQ_fx+12, YG_mean16_fx+12, YG_dicMR_4_fx, idx_g_fx, 4 );
}
}
/* Gain adjustment to fit ACELP generic inactive coding gain at low rate */
GSC_gain_adj(coder_type_fx, core_brate_fx, mean_4g_fx, old_y_gain_fx, y_gainQ_fx, y_gainQ_fx);
return mean_4g_fx;
}
/*-------------------------------------------------------------------*
* gsc_gainQ()
*
* Quantization of the energy per band
*-------------------------------------------------------------------*/
Word16 gsc_gainQ_fx( /*Q12*/
Encoder_State_fx *st_fx, /* i/o: decoder state structure */
const Word16 y_gain4[], /* i : Energy per band Q12 */
Word16 y_gainQ[], /* o : quantized energy per band Q12 */
const Word32 core_brate, /* i : Core rate */
const Word16 coder_type, /* i : coding type */
const Word16 bwidth /* i : input signal bandwidth */
)
{
Word16 y_gain_tmp[MBANDS_GN], y_gain_tmp2[MBANDS_GN];
Word16 i, idx_g = 0;
Word16 mean_4g[1] = {0}, tmp16,tmp1, tmp2;
Word16 Mbands_gn = MBANDS_GN;
Word16 y_gain_tmp3[MBANDS_GN];
Word16 cnt;
Word32 L_tmp;
mean_4g[0] = 0;
test();
test();
IF( (sub(coder_type,AUDIO) == 0 || sub(coder_type,INACTIVE) == 0) && sub(bwidth,NB) == 0 )
{
/*ftmp1 = mean(y_gain4, 10)-0.6f;*/
L_tmp = L_deposit_l(0);
FOR(cnt = 0 ; cnt < 10 ; cnt++)
{
L_tmp = L_mac(L_tmp,y_gain4[cnt], 3277);
}
tmp16 = sub(round_fx(L_tmp), 4915);
FOR(i = 0; i < Mbands_gn; i++)
{
y_gain_tmp2[i] = y_gain4[i];
move16();
/*if(y_gain4[i] < ftmp1-0.6f)*/
y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp16);
move16();
}
L_tmp = L_deposit_l(0);
FOR(i = 0; i < 10; i++)
{
L_tmp = L_mac(L_tmp,y_gain_tmp2[i], 3277);
}
/* Quantized mean gain without clipping */
mean_4g[0] = round_fx(L_tmp);
idx_g = vquant_fx(mean_4g, Gain_meanNB_fx, mean_4g, Gain_mean_dicNB_fx, 1, 64);
push_indice_fx( st_fx, IND_MEAN_GAIN2, idx_g, 6 );
FOR(i = 0; i < Mbands_gn; i++)
{
y_gain_tmp[i] = sub(y_gain_tmp2[i],mean_4g[0]);
move16();
}
/*if(y_gain_tmp[9] < -0.3f){y_gain_tmp[9] = -0.3f;}*/
y_gain_tmp[9] = s_max(y_gain_tmp[9], -1229);
move16();
set16_fx(y_gain_tmp+10, 0, MBANDS_GN-10);
idx_g = vquant_fx(y_gain_tmp, Mean_dic_NB_fx, y_gain_tmp, Gain_dic1_NB_fx, 3, 64);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 );
IF(L_sub(core_brate,ACELP_9k60) < 0)
{
idx_g = vquant_fx(y_gain_tmp+3, Mean_dic_NB_fx+3, y_gain_tmp+3, Gain_dic2_NB_fx, 3, 32);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
idx_g = vquant_fx(y_gain_tmp+6, Mean_dic_NB_fx+6, y_gain_tmp+6, Gain_dic3_NB_fx, 4, 16);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 4 );
}
ELSE
{
idx_g = vquant_fx(y_gain_tmp+3, Mean_dic_NB_fx+3, y_gain_tmp+3, Gain_dic2_NBHR_fx, 3, 64);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 );
idx_g = vquant_fx(y_gain_tmp+6, Mean_dic_NB_fx+6, y_gain_tmp+6, Gain_dic3_NBHR_fx, 4, 128);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 7 );
}/*add end */
test();
IF( L_sub(core_brate,ACELP_9k60) <= 0 && sub(coder_type,INACTIVE) == 0 )
{
/* Some energy is needed in high band for stat_noise_uv_enc
to be functional in inactive speech */
y_gain_tmp[10] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[6],8192),y_gain_tmp[7],8192),y_gain_tmp[8],8192));
y_gain_tmp[11] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[7],8192),y_gain_tmp[8],8192),y_gain_tmp[9],8192));
y_gain_tmp[12] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[8],8192),y_gain_tmp[9],8192),y_gain_tmp[10],8192));
y_gain_tmp[13] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[9],8192),y_gain_tmp[10],8192),y_gain_tmp[11],8192));
y_gain_tmp[14] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[10],8192),y_gain_tmp[11],8192),y_gain_tmp[12],8192));
y_gain_tmp[15] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[11],8192),y_gain_tmp[12],8192),y_gain_tmp[13],8192));
}
ELSE
{
set16_fx( y_gain_tmp + 10, 0, MBANDS_GN - 10 );
}
}
ELSE
{
/*ftmp1 = mean(y_gain4, 16);*/
L_tmp =0;
FOR(cnt = 0 ; cnt < 16 ; cnt++)
{
L_tmp = L_mac(L_tmp,y_gain4[cnt], 2048);
}
tmp16 = round_fx(L_tmp);
tmp1 = sub(tmp16,4915);
tmp2 = add(tmp16,4915);
L_tmp =0;
FOR(i = 0; i < 16; i++)
{
y_gain_tmp2[i] = y_gain4[i];
move16();
/*if(y_gain4[i] < ftmp1-0.6f)*/
y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp1);
move16();
/*else if(y_gain4[i] > ftmp1+0.6f)*/
y_gain_tmp2[i] = s_min(y_gain_tmp2[i], tmp2);
move16();
L_tmp = L_mac(L_tmp,y_gain_tmp2[i], 2048);
}
FOR(; i < Mbands_gn; i++)
{
y_gain_tmp2[i] = y_gain4[i];
/*if(y_gain4[i] < ftmp1-0.6f)*/
y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp1); /* Just the last move is needed, because s_max and s_min could be done in 1 line*/
/*else if(y_gain4[i] > ftmp1+0.6f)*/
y_gain_tmp2[i] = s_min(y_gain_tmp2[i], tmp2);
move16();
}
/* Quantized mean gain without clipping */
mean_4g[0] = round_fx(L_tmp);
/*idx_g = (short)vquant(mean_4g, mean_m, mean_4g, mean_gain_dic, 1, 64);*/
idx_g = vquant_fx(mean_4g, mean_m_fx, mean_4g, mean_gain_dic_fx, 1, 64);
push_indice_fx( st_fx, IND_MEAN_GAIN2, idx_g, 6 );
FOR(i = 0; i < Mbands_gn; i++)
{
y_gain_tmp[i] = sub(y_gain_tmp2[i],mean_4g[0]);
move16();
}
IF( L_sub(core_brate,ACELP_9k60) < 0 )
{
/*mvr2r(y_gain_tmp, y_gain_tmp2, 8); */
Copy(y_gain_tmp, y_gain_tmp2, 8);
y_gain_tmp2[8] = y_gain_tmp[8];
move16();
y_gain_tmp2[9] = y_gain_tmp[10];
move16();
y_gain_tmp2[10] =y_gain_tmp[12];
move16();
y_gain_tmp2[11] =y_gain_tmp[14];
move16();
idx_g = 0;
/*idx_g = (short)vquant(y_gain_tmp2, YGain_mean_LR, y_gain_tmp2, YGain_dic1_LR, 3, 32);*/
idx_g = vquant_fx(y_gain_tmp2, YGain_mean_LR_fx, y_gain_tmp2, YGain_dic1_LR_fx, 3, 32 );
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
/*idx_g = (short)vquant(y_gain_tmp2+3, YGain_mean_LR+3, y_gain_tmp2+3, YGain_dic2_LR, 4, 32);*/
idx_g = vquant_fx(y_gain_tmp2+3, YGain_mean_LR_fx+3, y_gain_tmp2+3, YGain_dic2_LR_fx, 4, 32 );
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
/*idx_g = (short)vquant(y_gain_tmp2+7, YGain_mean_LR+7, y_gain_tmp2+7, YGain_dic3_LR, 5, 32);*/
idx_g = vquant_fx(y_gain_tmp2+7, YGain_mean_LR_fx+7, y_gain_tmp2+7, YGain_dic3_LR_fx, 5, 32);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
/*set_f(y_gain_tmp2+12, 0, MBANDS_GN-12);*/
set16_fx(y_gain_tmp2+12, 0, MBANDS_GN-12);
/* Update to quantized vector */
Copy(y_gain_tmp2, y_gain_tmp, 8);
Copy(y_gain_tmp2+8, y_gain_tmp3, 4);
set16_fx(y_gain_tmp+8, 0,8);
fft_rel_fx(y_gain_tmp2+8, 4, 2);
Copy(y_gain_tmp2+8, y_gain_tmp+8, 3);
y_gain_tmp[15] = y_gain_tmp2[11];
ifft_rel_fx(y_gain_tmp+8, 8, 3);
FOR(i = 8; i < 16; i++)
{
/*y_gain_tmp[i] *= 1.41f;*/
y_gain_tmp[i] = shl( mult_r(y_gain_tmp[i] , 23101),1) ;
move16();
}
y_gain_tmp[8] = y_gain_tmp3[0];
move16();
y_gain_tmp[10]= y_gain_tmp3[1];
move16();
y_gain_tmp[12]= y_gain_tmp3[2];
move16();
y_gain_tmp[14]= y_gain_tmp3[3];
move16();
}
ELSE
{
idx_g = vquant_fx(y_gain_tmp, YG_mean16_fx, y_gain_tmp, YG_dicMR_1_fx, 4, 64);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 );
idx_g = vquant_fx(y_gain_tmp+4, YG_mean16_fx+4, y_gain_tmp+4, YG_dicMR_2_fx, 4, 32);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
idx_g = vquant_fx(y_gain_tmp+8, YG_mean16_fx+8, y_gain_tmp+8, YG_dicMR_3_fx, 4, 32);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 );
idx_g = vquant_fx(y_gain_tmp+12, YG_mean16_fx+12, y_gain_tmp+12, YG_dicMR_4_fx, 4, 16);
push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 4 );
}
}
/* Gain adjustment to fit ACELP generic inactive coding gain at low rate */
GSC_gain_adj(coder_type, core_brate, mean_4g[0], y_gain_tmp2 /* dummy buffer */, y_gain_tmp, y_gainQ);
return mean_4g[0]; /*Q12*/
}
/*-------------------------------------------------------------------*
* VDQ_vec()
*
* Return the dequantized vector of index
*-------------------------------------------------------------------*/
static Word16 VDQ_vec_fx(
Word16 *Qvec_out_fx, /* o: Quanitzed vector */
const Word16 *mean_dic_fx, /* i: average codebook */
const Word16 *dic_fx, /* i: codebook */
const Word16 index_fx, /* i: index of codebook*/
const Word16 vec_en_fx /* i: vector length */
)
{
Word16 i, j;
/*j = shr_r(extract_l(L_mult(index_fx,vec_en_fx)),1);*/
j = i_mult2(index_fx,vec_en_fx);
FOR ( i = 0; i < vec_en_fx; i++)
{
Qvec_out_fx[i] = dic_fx[j++];
move16();
}
FOR(i = 0; i < vec_en_fx; i++)
{
Qvec_out_fx[i] = add(Qvec_out_fx[i],mean_dic_fx[i]);
move16();
}
return index_fx;
}
+153
View File
@@ -0,0 +1,153 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
#define ALPHA0_FX 13107
#define BETA0_FX (32768-ALPHA0_FX)
/*========================================================================*/
/* FUNCTION : Inac_swtch_ematch_fx() */
/*------------------------------------------------------------------------*/
/* PURPOSE : Apply energy matching when swithcing to INACTIVE frame coded */
/* by the GSC technology */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) coder_type : Coding mode */
/* _ (Word16) L_frame : Frame lenght */
/* _ (Word32) core_brate : core bitrate */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16[]) exc2 : CELP/GSC excitation buffer Q_exc */
/* _ (Word16[]) lt_ener_per_band : Long term energy per band Q12 */
/* _ (Word16*) Q_exc : input and output format of exc2 */
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
void Inac_swtch_ematch_fx(
Word16 exc2[], /* i/o: CELP/GSC excitation buffer Q_exc*/
Word16 dct_exc_tmp[], /* i : GSC excitation in DCT domain */
Word16 lt_ener_per_band[], /* i/o: Long term energy per band Q12 */
const Word16 coder_type, /* i : Coding mode */
const Word16 L_frame, /* i : Frame lenght */
const Word32 core_brate, /* i : Core bit rate */
const Word16 Q_exc /* i : input and output format of exc2 */
,const Word16 bfi /* i : frame lost indicator */
,const Word16 last_core, /* i : Last core used */
const Word16 last_codec_mode /* i : Last codec mode */
)
{
Word16 Ener_per_bd[MBANDS_GN];
Word16 ftmp;
Word16 *pt_exc;
Word16 j, i;
Word16 exp,frac;
Word32 L_tmp;
/*--------------------------------------------------------------------------
* average energy per band
*--------------------------------------------------------------------------*/
test();
test();
test();
test();
test();
test();
IF(sub(coder_type,AUDIO) == 0 && bfi == 0)
{
Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1);
/* reset long-term energy per band */
FOR(i = 0; i < MBANDS_GN; i++)
{
lt_ener_per_band[i] = Ener_per_bd[i];
move16();
}
}
ELSE IF( sub(coder_type,VOICED) == 0 || sub(coder_type,GENERIC) == 0 || sub(coder_type,TRANSITION) == 0 || sub(last_core,ACELP_CORE) != 0 || sub(last_codec_mode,MODE1) != 0 )
{
/* Find spectrum and energy per band for GC and VC frames */
edct_16fx( exc2, dct_exc_tmp, L_frame, 5 );
Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1);
/* reset long-term energy per band */
FOR(i = 0; i < MBANDS_GN; i++)
{
lt_ener_per_band[i] = Ener_per_bd[i];
move16();
}
}
ELSE IF( sub(coder_type,INACTIVE) == 0 && L_sub(core_brate,ACELP_24k40) <= 0)
{
/* Find spectrum and energy per band for inactive frames */
edct_16fx( exc2, dct_exc_tmp, L_frame, 5 );
Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1 );
/* More agressive smoothing in the first 50 frames */
pt_exc = dct_exc_tmp;
move16();
FOR(i = 0; i < MBANDS_GN; i++)
{
/* Compute smoothing gain to apply with gain limitation */
L_tmp = L_mult(ALPHA0_FX,lt_ener_per_band[i]); /*Q(15+12+1)=Q(28) */
L_tmp = L_mac(L_tmp,BETA0_FX,Ener_per_bd[i]); /*Q28 */
lt_ener_per_band[i] = round_fx(L_tmp); /*Q12 */
ftmp = sub(lt_ener_per_band[i],Ener_per_bd[i]); /*Q12 */
/* ftmp = (float)pow(10, ftmp);= pow(2,3.321928*ftmp);*/
L_tmp = L_mult(27213,ftmp); /*Q(13+12+1)=Q26 ; 27213=3.321928 in Q13 */
L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of ftmp */
ftmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16384 < Pow2() <= 32767 */
exp = sub(exp,14);
IF( sub(i,2) < 0 )
{
FOR (j = 0; j < 8; j ++)
{
L_tmp = L_mult(*pt_exc,ftmp); /* Q_exc*Q0 -> Q(Q_exc+1) */
L_tmp = L_shl(L_tmp, add(exp,15)); /* Q(Q_exc+1) -> Q(16+Q_exc)*/
*pt_exc = round_fx(L_tmp);
pt_exc++;
}
}
ELSE
{
FOR (j = 0; j < 16; j ++)
{
L_tmp = L_mult(*pt_exc,ftmp); /* Q_exc*Q0 -> Q(Q_exc+1) */
L_tmp = L_shl(L_tmp, add(exp,15)); /* Q(Q_exc+1) -> Q(16+Q_exc)*/
*pt_exc = round_fx(L_tmp); /*Q_exc*/
pt_exc++;
}
}
}
/* Going back to time */
edct_16fx( dct_exc_tmp, exc2, L_frame, 5 );
}
return;
}
+921
View File
@@ -0,0 +1,921 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "rom_com_fx.h"
#include "prot_fx.h"
#include "stl.h"
/*-------------------------------------------------------------------*
* gs_noisf()
*
* Noise fill-in function
*-------------------------------------------------------------------*/
static void gs_noisf_fx(
const Word16 Start_BIN, /* i : First bin for noise fill */
const Word16 NB_Qbins, /* i : Number of bin per band */
const Word16 Noise_fac, /* i : Noise level Q15 */
const Word16 *y_norm, /* i : Quantized pulses Qn */
Word16 *exc_diffQ, /* o : Quantized pulses with noise added Qn */
Word16 *seed_tcx, /* i : Random generator seed */
const Word16 coder_type, /* i : coder type */
Word16 qNoise_fac
)
{
Word32 ftmp;
Word16 i, k;
Word16 NB_zer;
Word32 const_1=1;
Word16 tmp;
NB_zer = shr(NB_Qbins,1);
const_1 = L_shl(const_1, add(qNoise_fac, qNoise_fac));
if( sub(coder_type,INACTIVE) == 0 )
{
NB_zer = 2;
move16();
}
/*----------------------------------------------*
* noise fill-in on unquantized subvector *
* injected only from 1066Hz to 6400Hz. *
*----------------------------------------------*/
FOR( k=Start_BIN; k<NB_Qbins + Start_BIN; k+=NB_zer )
{
ftmp = L_deposit_l(0);
FOR(i=k; i<k+NB_zer; i++)
{
exc_diffQ[i] = y_norm[i];
move16();
ftmp = L_mac0(ftmp, exc_diffQ[i], exc_diffQ[i]);
}
IF (L_sub(L_shl(ftmp, 1),const_1) < 0)
{
FOR(i=k; i<k+NB_zer; i++)
{
/*exc_diffQ[i] += Noise_fac*((float)own_random(seed_tcx)/32768.0f);*/
tmp = mult(Noise_fac, Random(seed_tcx));/*Q15 */
tmp = shr(tmp, sub(15,qNoise_fac));/*qNoise_fac */
exc_diffQ[i] = add(exc_diffQ[i], tmp);
move16();/*Q */
}
}
ELSE
{
/* This is added only to keep the seed in sync between different compilers */
FOR(i=k; i<k+NB_zer; i++)
{
Random(seed_tcx);
}
}
}
return;
}
/*-------------------------------------------------------------------*
* EstimateNoiseLevel_inner()
*
* Estimate noise level from the power spectrum
*-------------------------------------------------------------------*/
static void EstimateNoiseLevel_inner_fx(
Word16 *noisepb, /* o : Noise per band Q15 */
const long bitrate, /* i : Bitrate of the codec */
const Word16 i_band, /* i : First band to compute the noise */
const Word16 Mbands_gn /* i : number of bands */
)
{
Word16 i;
Word16 noise_offset;
noise_offset = 8192;
move16();
/*0.25f * 32768 */
IF( bitrate > ACELP_24k40 )
{
noise_offset = 6554;
move16(); /*.2f * 32768 */
}
ELSE IF ( bitrate >= ACELP_22k60 )
{
noise_offset = 9830;
move16();/*.3f * 32768 */
}
ELSE IF ( bitrate >= ACELP_9k60 )
{
noise_offset = 11469;
move16(); /*0.35f * 32768 */
}
ELSE
{
noise_offset = 13107;
move16(); /*.4f * 32768 */
}
set16_fx( noisepb + i_band, noise_offset, sub(Mbands_gn, i_band) );
FOR( i = i_band; i < 5; i++ )
{
noisepb[i] = s_min(noisepb[i], 6554);
move16();
}
return;
}
/*==========================================================================*/
/* FUNCTION : void EstimateNoiseLevel_fx() */
/*--------------------------------------------------------------------------*/
/* PURPOSE : */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word32) bitrate : Bitrate of the codec Q0 */
/* _ (Word16) Diff_len : number of bin before cut-off frequency */
/* _ (Word16) Mbands_gn : number of bands Q0 */
/* _ (Word16) coder_type : coder type Q0 */
/* _ (Word16) noise_lev : pulses dynamic Q0 */
/* _ (Word16) pit_band_idx : bin position of the cut-off frequency */
/* _ (Word16*) freq_nsbin_per_band : bin per bands tables Q0 */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) noisepb : Noise per band Q15 */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* None */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*==========================================================================*/
static void EstimateNoiseLevel_fx(
Word16 *noisepb, /* o : Noise per band */
const Word32 bitrate, /* i : Bitrate of the codec */
const Word16 Diff_len, /* i : number of bin before cut-off frequency */
const Word16 Mbands_gn, /* i : number of bands */
const Word16 coder_type, /* i : coder type */
const Word16 noise_lev, /* i : pulses dynamic */
const Word16 pit_band_idx, /* i : bin position of the cut-off frequency */
Word16 last_bin, /* i : the last bin of bit allocation */
Word16 bwidth
)
{
Word16 i_band;
i_band = 0;
move16();
IF( sub(Diff_len,L_FRAME) < 0)
{
EstimateNoiseLevel_inner_fx(noisepb, bitrate, i_band, MBANDS_GN);
IF( coder_type != INACTIVE )
{
test();
test();
IF( (L_sub(bitrate,ACELP_8k00) == 0 && sub(last_bin,8) > 0) && sub(bwidth,NB) != 0)
{
FOR( ; Mbands_gn > i_band; i_band++)
{
noisepb[i_band] = add(noisepb[i_band],noisepb[i_band]);
move16();
}
}
ELSE
{
FOR( ; pit_band_idx > i_band; i_band++ )
{
noisepb[i_band] = mult_r(noisepb[i_band], 16384);
move16();/* 1/2=0.5 in Q15 */
}
}
}
}
test();
IF ( (sub(coder_type,INACTIVE) == 0 || sub(noise_lev,NOISE_LEVEL_SP3) >= 0) )
{
FOR( i_band = 9; i_band < Mbands_gn; i_band++ )
{
noisepb[i_band] = add(noisepb[i_band], mult_r(noisepb[i_band], 4915));
move16();/*noisepb[i_band]*1.15=noisepb[i_band] *(1 + 0.15) */
}
}
return;
}
/*============================================================================*/
/* FUNCTION : void Appy_NoiseFill_fx() */
/*----------------------------------------------------------------------------*/
/* PURPOSE : */
/*----------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16*) seed_tcx : Seed for noise Q0 */
/* _ (Word16*) noisepb : Noise per band Q15 */
/* _ (Word16) Diff_len : number of bin before cut-off frequency Q0 */
/* _ (Word16) Mbands_gn : number of bands Q0 */
/* _ (Word16) coder_type : pulses dynamic Q0 */
/* _ (Word16*) freq_nsbin_per_band: bin per bands tables Q0 */
/* _ (Word16) qexc_diffQ : Q format of exc_diffQ */
/*----------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) exc_diffQ : Noise per band qexc_diffQ */
/*----------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* None */
/*----------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*============================================================================*/
static void Apply_NoiseFill_fx(
Word16 *exc_diffQ, /* i/o: Noise per band qexc_diffQ */
Word16 *seed_tcx, /* i : Seed for noise */
const Word16 *noisepb, /* i : Noise per band Q15 */
const Word16 Diff_len, /* i : number of bin before cut-off frequency */
const Word16 Mbands_gn, /* i : number of bands */
const Word16 coder_type, /* i : coder type */
const Word16 *freq_nsbin_per_band, /* i : bin per bands tables */
Word16 qexc_diffQ
)
{
Word16 StartBin, NB_Qbins, i_band;
StartBin = 0;
move16();
NB_Qbins = 0;
move16();
FOR( i_band = 0; i_band < Mbands_gn; i_band++ )
{
StartBin += NB_Qbins;
move16();
NB_Qbins = freq_nsbin_per_band[i_band];
move16();
IF( sub(Diff_len,L_FRAME) < 0 )
{
gs_noisf_fx( StartBin , NB_Qbins, noisepb[i_band], exc_diffQ, exc_diffQ, seed_tcx, coder_type, qexc_diffQ);
}
}
return;
}
/*==========================================================================*/
/* FUNCTION :void freq_dnw_scaling_fx () */
/*--------------------------------------------------------------------------*/
/* PURPOSE : */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) cor_strong_limit : HF correlation Q0 */
/* _ (Word16) coder_type : coder type Q0 */
/* _ (Word16) noise_lev : Noise level Q0 */
/* _ (Word32) core_brate : Core bitrate Q0 */
/* _ (Word16) Qx : Q format of fy_norm */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16[]) fy_norm : Frequency quantized parameter Qx */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _None */
/*==========================================================================*/
void freq_dnw_scaling_fx(
const Word16 cor_strong_limit, /* i : HF correlation */
const Word16 coder_type, /* i : coder type */
const Word16 noise_lev, /* i : Noise level */
const Word32 core_brate, /* i : Core bitrate */
Word16 fy_norm[], /* i/o: Frequency quantized parameter */
Word16 Qx /* Q format of fy_norm*/
)
{
Word16 sc_dyn;
Word16 start_sc, i;
sc_dyn = 32767;
move16(); /*Q15 */
start_sc = L_FRAME;
move16();
test();
IF( L_sub(core_brate,ACELP_8k00) <= 0 && sub(coder_type,INACTIVE) == 0 )
{
sc_dyn = mult_r(sc_dyn,4915); /*Q15 (0.15 in Q15) */
start_sc = 64;
move16();
}
ELSE IF ( sub(coder_type,INACTIVE) == 0 )
{
sc_dyn = mult_r(sc_dyn,8192); /*Q15 (0.25 in Q15) */
start_sc = 80;
move16();
}
ELSE
{
/*sc_dyn = (float)(NOISE_LEVEL_SP3 - noise_lev)/10.0f + 0.4f;*/
sc_dyn = extract_l(L_mac(13107, sub(NOISE_LEVEL_SP3, noise_lev), 1638)); /*Q0*Q14x2+Q15 =Q15*/
start_sc = add(112, shl(sub(NOISE_LEVEL_SP3, noise_lev), 4));
if( sub(noise_lev,NOISE_LEVEL_SP0) == 0)
{
start_sc = L_FRAME;
move16();
}
}
FOR(i = start_sc; i < L_FRAME; i++)
{
fy_norm[i] = mult_r(fy_norm[i],sc_dyn);
move16();/*Qx */
}
test();
test();
IF( (L_sub(core_brate,ACELP_13k20) < 0 && cor_strong_limit == 0) || L_sub(core_brate,ACELP_9k60) < 0)
{
FOR(i = 160; i < L_FRAME; i++)
{
fy_norm[i] = s_min(fy_norm[i],shl(1,Qx));
move16();
fy_norm[i] = s_max(fy_norm[i],shl(-1,Qx));
move16();
}
}
ELSE IF ( L_sub(core_brate,ACELP_22k60) < 0 )
{
FOR(i = 160; i < L_FRAME; i++)
{
fy_norm[i] = s_min(fy_norm[i],shr_r(1536,sub(10,Qx)));
move16();
fy_norm[i] = s_max(fy_norm[i],shr_r(-1536,sub(10,Qx)));
move16();
}
}
return;
}
static void Decreas_freqPeak_fx(
Word16 *lsf_new, /* i : ISFs at the end of the frame */
Word16 *exc_diffQ, /* i/o: frequency coefficients of per band */
Word16 rat /* i : threshold of ratio between consecutive lsf_new_diff */
)
{
Word16 i, j, k;
Word16 last_bin = 0;
Word16 pos = 0;
Word16 *src, max,avrg;
Word32 L_avrg,L_tmp;
Word16 lsf_new_diff[M];
Word16 tmp,tmp1,exp;
Word16 tmp2;
move16(); /*ptr init*/
lsf_new_diff[0] = 0; /* prevent unitialized value */
FOR(j=1; j<(M-1); j++)
{
lsf_new_diff[j] =sub( lsf_new[j] , lsf_new[j-1]);/*Qx2.56 */
}
avrg = 0;
move16();
L_avrg = L_deposit_l(0);
max = 1;
move16();
FOR(i=160; i<L_FRAME; i++)
{
IF(sub(abs_s(exc_diffQ[i]),max) > 0)
{
max = abs_s(exc_diffQ[i]);
pos = i;
move16();
}
L_avrg = L_add(L_avrg,abs_s(exc_diffQ[i]));
}
/* avrg /= 96; */
L_avrg = Mult_32_16(L_avrg,21845);/*Q_exc+21 -15 ->Q_exc + 6 */
avrg = round_fx(L_shl(L_avrg,10));/*Q_exc */
last_bin = M-1;
move16(); /* When the search is false, should equate the end of the vector, not the beginning */
FOR(i=0; i<(M-1); i++)
{
if(sub(lsf_new[i],10240) > 0)
{
last_bin = i;
move16();
BREAK;
}
}
FOR(i=last_bin; i<14; i++)
{
tmp = mult_r(rat,lsf_new_diff[i-1] );/*Qx2.56 */
IF(sub(tmp , lsf_new_diff[i])>0)
{
src = &exc_diffQ[shl(sub(i,1),4)];
move16();
FOR(j=0; j<2; j++)
{
FOR(k=0; k<16; k++)
{
tmp = mult_r(16384,abs_s(*src));
IF(sub(tmp,avrg)>0)
{
tmp = abs_s(*src) ;
exp = norm_s(max);
tmp1 = div_s(shl(1,sub(14,exp)),max);/*Q(29 - exp - Q_exc) */
L_tmp = L_mult(tmp,tmp1);/*Q(30 - exp) */
tmp = round_fx(L_shl(L_tmp,exp));/*Q14 */
tmp = sub(32767,tmp);/*Q14 */
L_tmp = L_mult(avrg,tmp);/*Q_exc +15 */
tmp = round_fx(L_shl(L_tmp,1));
tmp1 = negate(tmp);
tmp2 = *src;
*(src) = tmp1;
move16();
if( tmp2 > 0 )
{
*(src) = tmp;
move16();
}
}
src++;
}
}
}
}
tmp = mult_r(8192,max);/*Q_exc */
test();
IF(sub(abs_s(exc_diffQ[pos]),max) == 0 && sub(tmp ,avrg)>0)
{
FOR(i=pos-1; i<pos+2; i++)
{
exc_diffQ[pos] =mult_r(16384,exc_diffQ[pos]);
move16();
}
}
return;
}
static void envelop_modify_fx(
Word16 *exc_diffQ_fx, /* i/o: frequency coefficients of per band */
Word16 *seed_tcx, /* i : Seed for noise */
Word16 last_bin, /* i : last bin of bit allocation */
Word16 *Ener_per_bd_iQ_fx, /* i : Quantized energy of targeted vector */
Word16 Q_exc,
Word16 *Q_hb_exc
)
{
Word16 i, j, end_band;
Word16 start_band;
Word32 Ener_fx;
Word16 Ener1_fx;
Word16 tmp, tmp1;
Word32 L_tmp;
Word16 exp, exp1, frac;
Word16 *src_fx;
Word16 weight_fx;
Word32 L_exc_diffQ_fx[L_FRAME16k], exc_diffQ_max;
Word16 Q_tmp;
start_band = i_mult(last_bin, 16);
end_band = L_FRAME;
move16();
Ener_fx = L_deposit_l(0);
FOR(i=start_band; i<end_band; i++)
{
L_tmp = L_mult0(exc_diffQ_fx[i], exc_diffQ_fx[i]); /*2*Q_exc */
Ener_fx = L_add(Ener_fx, L_shr(L_tmp, 7)); /*2*Q_exc-7 */
}
tmp = sub(end_band, start_band);
tmp = div_s(1, tmp);/*Q15 */
Ener_fx = Mult_32_16(Ener_fx, tmp); /*Q(2*Q_exc-7+15)->Q(2*Q_exc-7) */
exp1 = norm_l(Ener_fx);
Ener_fx = L_shl(Ener_fx, exp1);
exp1 = 31-exp1-sub(shl(Q_exc,1),7);
move16();
Ener_fx = Isqrt_lc(Ener_fx, &exp1); /*Q(31-exp1) */
weight_fx = 16384; /*Q15 */
src_fx = &exc_diffQ_fx[start_band]; /*Q_exc */
FOR(i=last_bin; i<last_bin+4; i++)
{
/*Ener1 = (float)(0.4f*pow(10, Ener_per_bd_iQ[i+1])); */
L_tmp = L_shr(L_mult0(Ener_per_bd_iQ_fx[i+1], 27213), 9); /* 3.321928 in Q13 -> Q16 */
frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */
tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16384 < Pow2() <= 32767 */
exp = sub(exp, 14);
Ener1_fx = mult_r(13107, shl(tmp, exp)); /*Q0 */
FOR(j=0; j<16; j++)
{
/**src = Ener1*(weight*(*src)*Ener + (1.0f-weight)*own_random(seed_tcx)/32768.0f); */
L_tmp = Mult_32_16(Ener_fx, *src_fx); /*Q(31-exp+Q_exc-15) -> Q(16-exp+Q_exc) */
tmp = extract_l(L_shr(L_tmp, add(4, sub(Q_exc, exp1)))); /*Q12 */
tmp = mult_r(weight_fx, tmp); /*Q12 */
L_tmp = L_mult0(sub(32767, weight_fx), Random(seed_tcx)); /*Q30 */
tmp1 = round_fx(L_shr(L_tmp, 2));
L_exc_diffQ_fx[16*i+j] = L_mult0(Ener1_fx, add(tmp, tmp1)); /*Q12 */ move32();
src_fx++;
}
}
/*Ener1 = (float)(0.4f*pow(10, Ener_per_bd_iQ[15])); */
L_tmp = L_shr(L_mult0(Ener_per_bd_iQ_fx[15], 27213), 9); /* 3.321928 in Q13 -> Q16 */
frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */
tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16384 < Pow2() <= 32767 */
exp = sub(exp, 14);
Ener1_fx = mult_r(13107, shl(tmp, exp)); /*Q0 */
src_fx = &exc_diffQ_fx[224];
FOR(j=0; j<32; j++)
{
/**src = Ener1*(weight*(*src)*Ener + (1.0f-weight)*own_random(seed_tcx)/32768.0f); */
L_tmp = Mult_32_16(Ener_fx, *src_fx); /*Q(31-exp+Q_exc-15) -> Q(16-exp+Q_exc) */
tmp = extract_l(L_shr(L_tmp, add(4, sub(Q_exc, exp1)))); /*Q12 */
tmp = mult_r(weight_fx, tmp); /*Q12 */
L_tmp = L_mult0(sub(32767, weight_fx), Random(seed_tcx)); /*Q30 */
tmp1 = round_fx(L_shr(L_tmp, 2)); /*Q12 */
L_exc_diffQ_fx[16*i+j] = L_mult0(Ener1_fx, add(tmp, tmp1)); /*Q12 */ move32();
src_fx++;
}
exc_diffQ_max = 0;
move16();
FOR(i=start_band; i<L_FRAME; i++)
{
IF(L_sub(L_abs(L_exc_diffQ_fx[i]), exc_diffQ_max) > 0)
{
exc_diffQ_max = L_abs(L_exc_diffQ_fx[i]);
}
}
exp = norm_l(exc_diffQ_max);
IF(sub(exp,16) > 0)
{
*Q_hb_exc = 12;
move16();
FOR(i=start_band; i<L_FRAME; i++)
{
exc_diffQ_fx[i] = extract_l(L_exc_diffQ_fx[i]);
}
}
ELSE
{
Q_tmp = sub(16, exp);
*Q_hb_exc = sub(12, Q_tmp);
FOR(i=start_band; i<L_FRAME; i++)
{
exc_diffQ_fx[i] = extract_l(L_shr(L_exc_diffQ_fx[i], Q_tmp));
}
}
return;
}
void highband_exc_dct_in_fx(
const Word32 core_brate, /* i : core bitrate */
const Word16 *mfreq_bindiv, /* i : bin per bands tables */
Word16 last_bin, /* i : last bin of bit allocation */
Word16 Diff_len, /* i : number of bin before cut-off frequency */
Word16 noise_lev, /* i : pulses dynamic */
Word16 pit_band_idx, /* i : bin position of the cut-off frequency */
Word16 *exc_diffQ, /* i : frequency coefficients of per band */
Word16 *seed_tcx, /* i : Seed for noise */
Word16 *Ener_per_bd_iQ, /* i : Quantized energy of targeted vector */
Word16 nb_subfr, /* i : Number of subframe considered */
Word16 *exc_dct_in, /* o : dct of residual signal */
Word16 last_coder_type, /* i : coding type of last frame */
Word16 *bitallocation_band, /* i : bit allocation flag of each band */
Word16 *lsf_new, /* i : LSFs at the end of the frame */
Word16 *last_exc_dct_in, /* i : dct of residual signal of last frame */
Word16 *last_ener, /* i : frequency energy of last frame */
Word16 *last_bitallocation_band, /* i : bit allocation flag of each band of last frame */
Word16 *bitallocation_exc, /* i : flag of decoded coefficients */
Word16 bfi, /* i : bad frame indicator */
const Word16 coder_type, /* i : coder type */
Word16 bwidth,
Word16 *exc_wo_nf , /* o : temporal excitation (in f domain) without noisefill */
Word16 Qexc_diffQ,
Word16 Q_exc,
const Word16 GSC_noisy_speech
,Word16 *lt_ener_per_band_fx /* i/o: Average per band energy */
)
{
Word16 i, j, k;
Word16 MAX_Bin = 0;
Word16 last_bin_tmp,ener=0;
Word16 noisepb[MBANDS_GN];
Word16 Ener_per_bd_yQ[MBANDS_GN];
Word16 *src, *dst;
Word32 L_tmp;
Word16 length_bin, bwe_flag = 0,tmp;
Word16 frac,exp,tmp1;
Word16 tmp2;
Word16 *end, Q_hb_exc;
FOR( j=10; j<MBANDS_GN; j++ )
{
/* ener += (float)pow(10, Ener_per_bd_iQ[j]);
ener += (float)pow(2, 3.321928*Ener_per_bd_iQ[j]); */
L_tmp = L_mult(Ener_per_bd_iQ[j], 27213); /* 3.321928 in Q13 -> Q27 */
L_tmp = L_shr(L_tmp, 10); /* From Q27 to Q16 */
frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */
tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
/* output of Pow2() will be: */
/* 16384 < Pow2() <= 32767 */
exp = sub(exp, 14);
tmp1 = shl(tmp,add(exp,0));
ener = add (tmp1,ener);/*Q0 */
}
test();
IF( L_sub(core_brate,ACELP_8k00) == 0 && sub(bwidth,NB) != 0 )
{
if(sub(last_coder_type,AUDIO) != 0)
{
*last_ener = ener;
move16();
}
test();
test();
IF((sub(last_bin,8) > 0 || Diff_len != 0) && sub(last_coder_type,AUDIO) == 0)
{
MAX_Bin = 10;
move16();
bwe_flag = 1;
move16();
}
ELSE
{
MAX_Bin = 15;
move16();
}
last_bin_tmp = last_bin;
move16();
last_bin = s_max(last_bin , MAX_Bin);
last_bin = add(last_bin, 1);
}
ELSE
{
last_bin = MBANDS_GN;
move16();
last_bin_tmp = last_bin;
move16();
}
IF( bfi )
{
set16_fx( noisepb, 13107, MBANDS_GN ); /*0.4 in Q15 */
}
ELSE
{
EstimateNoiseLevel_fx( noisepb, core_brate, Diff_len, last_bin, coder_type, noise_lev, pit_band_idx,
last_bin_tmp, bwidth );
}
IF( exc_wo_nf != NULL )
{
Copy( exc_diffQ, exc_wo_nf, L_FRAME );
}
test();
IF( GSC_noisy_speech && !bfi )
{
set16_fx( noisepb, 3277, MBANDS_GN );
}
Apply_NoiseFill_fx( exc_diffQ, seed_tcx, noisepb, Diff_len, last_bin, coder_type, mfreq_bindiv, Qexc_diffQ );
/*--------------------------------------------------------------------------------------*
* Quantize average gain
* Substract Q averaged gain
* VQ of remaining gain per band
*--------------------------------------------------------------------------------------*/
test();
IF( L_sub(core_brate,ACELP_8k00) == 0 && sub(bwidth,NB) != 0 )
{
Ener_per_band_comp_fx(exc_diffQ, Ener_per_bd_yQ, Qexc_diffQ, add(last_bin,1), 0);
}
ELSE
{
Ener_per_band_comp_fx(exc_diffQ, Ener_per_bd_yQ, Qexc_diffQ, MBANDS_GN, 1 );
IF( sub(nb_subfr, 4) < 0 )
{
FOR(i = L_FRAME-16; i < L_FRAME; i++)
{
/*exc_diffQ[i] *= 0.067f * i - 15.0f; = -15 - (-0.067f * i) */
tmp = msu_r(-7680*65536, -17564, shl(i,6));/*-15 in Q9; -0.067 in Q18 and i in Q6= Q9 */
L_tmp = L_mult(exc_diffQ[i],tmp); /*Q(Qexc_diffQ+10) */
exc_diffQ[i] = round_fx(L_shl(L_tmp,16-10));/*Qexc_diffQ */
}
}
}
/*--------------------------------------------------------------------------------------*
* Check potential energy excitation overshoot
*--------------------------------------------------------------------------------------*/
IF( bfi )
{
test();
IF (GSC_noisy_speech == 0 && sub(coder_type,UNVOICED) > 0 ) /* Here coder_type == last_coder_type because of the bfi */
{
FOR( i=0; i<last_bin; i++ )
{
Ener_per_bd_iQ[i]= s_min( Ener_per_bd_iQ[i], sub(sub(lt_ener_per_band_fx[i],154), Ener_per_bd_yQ[i]));
move16();
lt_ener_per_band_fx[i] = sub(lt_ener_per_band_fx[i], 77);
move16();
}
FOR(; i<MBANDS_GN; i++ )
{
Ener_per_bd_iQ[i]= s_min( Ener_per_bd_iQ[i], sub(lt_ener_per_band_fx[i],154));
move16();
lt_ener_per_band_fx[i] = sub(lt_ener_per_band_fx[i], 77);
move16();
}
}
ELSE
{
FOR( i=0; i<last_bin; i++ )
{
Ener_per_bd_iQ[i]= s_min( Ener_per_bd_iQ[i], sub(add(lt_ener_per_band_fx[i],1229), Ener_per_bd_yQ[i]));
move16();
lt_ener_per_band_fx[i] = sub(lt_ener_per_band_fx[i], 77);
move16();
}
FOR( ; i<MBANDS_GN; i++ )
{
Ener_per_bd_iQ[i]= s_min( Ener_per_bd_iQ[i], add(lt_ener_per_band_fx[i],1229));
move16();
lt_ener_per_band_fx[i] = sub(lt_ener_per_band_fx[i], 77);
move16();
}
}
}
/*--------------------------------------------------------------------------------------*
* Apply decoded gain onto the difference signal
*--------------------------------------------------------------------------------------*/
IF( GSC_noisy_speech )
{
FOR( i= 0; i < L_FRAME; i++ )
{
exc_diffQ[i] = mult_r(exc_diffQ[i], 29491);
move16();
}
}
Comp_and_apply_gain_fx( exc_diffQ, Ener_per_bd_iQ, Ener_per_bd_yQ, last_bin, 0, Qexc_diffQ, Q_exc );
IF( exc_wo_nf != NULL )
{
Comp_and_apply_gain_fx( exc_wo_nf, Ener_per_bd_iQ, Ener_per_bd_yQ, last_bin, 1 , Qexc_diffQ, Q_exc);
Vr_add( exc_dct_in, exc_wo_nf, exc_wo_nf, L_FRAME );
}
/*--------------------------------------------------------------------------------------*
* add the correction layer to the LF bins,
* and add the quantized pulses or the noise for the higher part of the spectrum
* (non valuable temporal content already zeroed)
* DC is Zeroed
*--------------------------------------------------------------------------------------*/
Vr_add( exc_dct_in, exc_diffQ, exc_dct_in, L_FRAME );
test();
IF( core_brate == ACELP_8k00 && bwidth != NB )
{
IF( sub(bwe_flag,1) == 0 )
{
last_bin = sub(last_bin, 1);
tmp = i_mult(MAX_Bin, 16);
tmp1 = i_mult(last_bin, 16);
src = &exc_diffQ[sub(L_FRAME,1)];
move16();
dst = &exc_dct_in[sub(tmp,1)];
move16();
end = &exc_diffQ[sub(tmp1,1)];
move16();
WHILE (src> end)
{
*src-- = *dst--;
move16();
}
test();
test();
if( (bitallocation_exc[0] != 0 || bitallocation_exc[1] != 0) && L_sub(core_brate, ACELP_8k00) == 0 )
{
exc_diffQ[160] = 0;
move16();
}
Q_hb_exc = 0;
move16();
envelop_modify_fx( exc_diffQ, seed_tcx, last_bin, Ener_per_bd_iQ, Q_exc, &Q_hb_exc);
Copy_Scale_sig( &exc_diffQ[tmp1], &exc_dct_in[tmp1], sub(L_FRAME,tmp1), sub(Q_exc, Q_hb_exc)); /* from Q_hb_exc -> Q_exc as expected */
}
IF( sub(nb_subfr,4) < 0 )
{
FOR( i = sub(L_FRAME,16); i < L_FRAME; i++ )
{
/*exc_dct_in[i] *= (0.067f*i-15.f); */
tmp = mult_r(17564,shl(i,6)); /*0.067 in Q18 and i in Q6= Q9 */
tmp = sub(tmp,7680); /*15 in Q9 = Q9 */
L_tmp = L_mult(exc_dct_in[i],tmp);/*Q(Q_exc+10) */
exc_dct_in[i] = round_fx(L_shl(L_tmp,6));/*Q_exc */
}
}
tmp1 = mult_r(ener,16384);
tmp1 = sub(*last_ener,tmp1);
tmp = mult_r(*last_ener,16384);
tmp = sub(ener,tmp);
test();
IF( tmp>0 && tmp1>0 )
{
length_bin = 6;
move16();
IF(last_coder_type != AUDIO)
{
set16_fx( last_bitallocation_band, 0, 6 );
Copy( &exc_dct_in[(4+length_bin)*16], &last_exc_dct_in[(4+length_bin)*16], length_bin*16 );
}
FOR(i=4; i<(4+length_bin); i++)
{
test();
IF( !(bitallocation_band[i] == 0 && last_bitallocation_band[i-4] == 0))
{
k = shl(add(i,length_bin),4);
src = &exc_dct_in[k]; /*(i+length_bin)*16*/
dst = &last_exc_dct_in[k];
FOR(j=0; j<16; j++)
{
tmp= mult_r(10923,abs_s(*src));
tmp1 =mult_r(10923,abs_s(*dst));
IF(sub(tmp,abs_s(*dst)) >0)
{
tmp2 = *src;
*src = mult_r(16384,sub(*src , abs_s(*dst))); /*Q_exc */ move16();
tmp = mult_r(16384,add(tmp2 , abs_s(*dst))); /*Q_exc */
if( tmp2 > 0 )
{
*src = tmp;
move16();
}
}
ELSE IF (sub(tmp1,abs_s(*src)) >0)
{
tmp = mult_r(*src,22938);
tmp1 = mult_r(9830,abs_s(*dst));
tmp2 = *src;
*src = sub(tmp,tmp1); /*Q_exc */ move16();
if( tmp2 > 0 )
{
*src = add(tmp,tmp1); /*Q_exc */ move16();
}
}
src++;
dst++;
}
}
}
}
IF(sub(bwe_flag,1) == 0)
{
Decreas_freqPeak_fx( lsf_new, exc_dct_in, 9830 );
}
ELSE
{
Decreas_freqPeak_fx( lsf_new, exc_dct_in, 16384 );
}
}
Copy( &exc_dct_in[64], &last_exc_dct_in[64], L_FRAME-64 );
Copy(&bitallocation_band[4], last_bitallocation_band, 6);
*last_ener = ener;
move16();
return;
}
+139
View File
@@ -0,0 +1,139 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
#define ATT_LENGHT 64
#define ATT_SEG_LEN (L_FRAME/ATT_LENGHT)
#define INV_ATT_SEG_LEN (1.0f/ATT_SEG_LEN)
#define INV_L_FRAME (1.0f/L_FRAME)
/*==========================================================================*/
/* FUNCTION : void pre_echo_att_fx(); */
/*--------------------------------------------------------------------------*/
/* PURPOSE : Attenuation of the pre-echo when encoder specifies an attack */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) L_frame_fx : length of the frame Q0 */
/* _ (Word16) gsc_attack_flag_fx : LP filter coefficient Q0 */
/* _ (Word16) core_fx : core codec used Q0 */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ (Word16*) exc_fx : adapt. excitation exc Q_exc */
/* _ (Word32*) Last_frame_ener_fx : Energy of the last frame Q1 */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*==========================================================================*/
void pre_echo_att_fx(
Word32 *Last_frame_ener_fx, /* i/o: Energy of the last frame 2*Q_new+1*/
Word16 *exc_fx, /* i/o: Excitation of the current frame Q_new*/
const Word16 gsc_attack_flag_fx /* i : flag signalling attack encoded by AC mode (GSC) */
,const Word16 Q_new
,const Word16 last_coder_type_fx /* i : Last coding mode */
)
{
Word32 etmp_fx;
Word32 finc_fx[ATT_LENGHT] = {0};
Word16 ratio_fx;
Word16 attack_pos_fx, i;
Word32 L_tmp, L_tmp1;
Word16 tmp, n1, n2, exp, frac1, frac2;
Word32 etmp1_fx;
test();
IF ( sub(gsc_attack_flag_fx,1) == 0 && sub(last_coder_type_fx, AUDIO) == 0) /*gsc_attack_flag_fx does not get set for all the test cases */
{
/*-------------------------------------------------------------------------*
* Find where the onset (attack) occurs by computing the energy per section
* The inverse weighting aims to favor the first maxima in case of
* gradual onset
*-------------------------------------------------------------------------*/
FOR(i = 0; i < ATT_LENGHT; i++)
{
L_tmp = sum2_fx(&exc_fx[shl(i,2)], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/
tmp = div_s(sub(ATT_LENGHT,i),ATT_LENGHT); /*Q15 */
L_tmp = Mult_32_16(L_tmp, tmp); /*2*Q_new+1 */
finc_fx[i] = L_tmp;
move32(); /*2*Q_new+1 */
}
attack_pos_fx = maximum_32_fx(finc_fx, ATT_LENGHT, &etmp_fx);
/* Scaled the maximum energy and allowed 6 dB increase*/
etmp_fx = L_shr(etmp_fx,add(2+1-4, shl(Q_new,1)));/*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */
etmp1_fx = etmp_fx;
move32();
*Last_frame_ener_fx = L_shl(*Last_frame_ener_fx,2);
move32(); /*2*Q_new+1 */
/* If the maximum normalized energy > last frame energy + 6dB */
test();
IF( L_sub(etmp_fx,*Last_frame_ener_fx) > 0 && attack_pos_fx > 0 )
{
/* Find the average energy before the attack */
L_tmp = sum32_fx( finc_fx, attack_pos_fx); /*Q1 */
L_tmp1 = L_shr(L_mult(attack_pos_fx,attack_pos_fx),1); /*Q0 */
tmp = round_fx(Isqrt(L_tmp1)); /*Q15 */
L_tmp = L_shr(L_tmp,2); /*Q1 ; ATT_SEG_LEN=4 */
etmp_fx = Mult_32_16(L_tmp,tmp); /*Q1 */
etmp_fx = L_shr(etmp_fx,add(1-4, shl(Q_new,1))); /* makes etmp i nQ4 as *Last_frame_ener_fx */
/* Find the correction factor and apply it before the attack */
/* ratio = (float)sqrt(*Last_frame_ener/etmp);*/
/* = isqrt(etmp/(*Last_frame_ener)) */
etmp_fx = L_max(etmp_fx,1);
*Last_frame_ener_fx = L_max(*Last_frame_ener_fx,1);
n1 = norm_l(etmp_fx);
n2 = norm_l(*Last_frame_ener_fx);
n1 = sub(n1,1);
exp = sub(n1,n2);
frac1 = round_fx(L_shl(etmp_fx,n1));
frac2 = round_fx(L_shl(*Last_frame_ener_fx,n2));
L_tmp = L_mult0(128, div_s(frac1, frac2)); /* s = gain_out / gain_in */
L_tmp = L_shr(L_tmp, exp); /* add exponent */
L_tmp = Isqrt(L_tmp);
ratio_fx = round_fx(L_shl(L_tmp, 9));
/* Pre-echo atttenuation should never increase the energy */
ratio_fx = s_min(ratio_fx, 8192);
FOR(i = 0; i < attack_pos_fx*ATT_SEG_LEN; i++)
{
/*exc_fx[i] *= ratio_fx;*/
exc_fx[i] = round_fx(L_shl(L_mac(-8192, exc_fx[i], ratio_fx), 2));
}
}
*Last_frame_ener_fx = etmp1_fx;
move32();
}
ELSE
{
/*-------------------------------------------------------*
* In normal cases, just compute the energy of the frame
*-------------------------------------------------------*/
etmp_fx = sum2_fx( exc_fx, L_FRAME ); /*2*Q_new+1 */
etmp_fx = L_shr(etmp_fx,add(8+1-4, shl(Q_new,1))); /*2*Q_new+1 //INV_L_FRAME = 1/256 -> Q4*/
*Last_frame_ener_fx = etmp_fx;
move32(); /*2*Q_new+1*/
}
return;
}
+324
View File
@@ -0,0 +1,324 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "prot_fx.h"
#include "stl.h"
#include "rom_com_fx.h"
#include "basop_util.h"
#include "rom_basop_util.h"
void getLookAheadResSig( Word16 *speechLookAhead, Word16 *A_3Q12, Word16 *res, Word16 L_frame, Word16 numSubFrame )
{
Word16 *p_A;
Word16 i_subfr;
Word16 subfr_len[2] = { L_SUBFR, L_SUBFR };
if( sub( L_FRAME16k, L_frame )>0 )
{
subfr_len[1] = 48;
move16(); /* 0.75 * L_SUBFR(64) */
}
p_A = A_3Q12;
FOR(i_subfr=0; i_subfr<numSubFrame*L_SUBFR; i_subfr+=L_SUBFR)
{
/* calculate residual signal */
Residu3_fx( p_A,
&speechLookAhead[i_subfr],
&res[i_subfr],
subfr_len[shr(i_subfr,6)],
0
);
/* pointer initialization */
p_A += (M+1);
}
return;
}
void updateLSFForConcealment( HANDLE_PLC_ENC_EVS decState, Word16 *lsf_14Q1, Word16 m )
{
Word16 i;
Word32 L_tmp = 0;
const Word16 divide_by_3_Q15 = 10923;
FOR (i=0; i<m; i++)
{
L_tmp = L_mult( divide_by_3_Q15, decState->lsfoldbfi1_14Q1[i] );
L_tmp = L_mac( L_tmp, divide_by_3_Q15, decState->lsfoldbfi0_14Q1[i] );
decState->lsf_adaptive_mean_14Q1[i] = mac_r( L_tmp, divide_by_3_Q15, lsf_14Q1[i] );
decState->lsfoldbfi1_14Q1[i] = decState->lsfoldbfi0_14Q1[i];
move16();
decState->lsfoldbfi0_14Q1[i] = lsf_14Q1[i];
move16();
}
return;
}
void getConcealedLP( HANDLE_PLC_ENC_EVS memDecState, Word16 *AqCon, const Word16 lsfBase[], Word16 last_good, Word16 L_frame)
{
Word16 *lsf;
Word16 lsp[(NB_DIV+1)*M];
Word32 int_fs;
move16();
lsf = memDecState->lsf_con;
dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold_14Q1, last_good,
1, memDecState->mem_MA_14Q1, memDecState->mem_AR, &(memDecState->stab_fac_Q15), memDecState->lsf_adaptive_mean_14Q1,
1,
NULL,
0,
NULL,
NULL,
lsfBase,
0
);
Copy( memDecState->lspold_Q15, lsp, M );
int_fs = INT_FS_FX;
move32();
if( sub(L_frame,L_FRAME_16k) == 0 )
{
int_fs = INT_FS_16k_FX;
move32();
}
lsf2lsp_fx( lsf, &lsp[M], M, int_fs );
int_lsp_fx( L_frame, &lsp[0], &lsp[M], AqCon, M, interpol_frac_fx, 0 );
return;
}
void getConcealedLSF( HANDLE_PLC_ENC_EVS memDecState, const Word16 lsfBase[], Word16 last_good, Word16 L_frame)
{
Word16 *lsf = memDecState->lsf_con;
dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold_14Q1, last_good,
1, memDecState->mem_MA_14Q1, memDecState->mem_AR, &(memDecState->stab_fac_Q15), memDecState->lsf_adaptive_mean_14Q1,
1,
NULL,
0,
NULL,
NULL,
lsfBase,
0
);
return;
}
static void reorder_lsfs(Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 sr_core);
void RecLpcSpecPowDiffuseLc( Word16 *lspq, Word16 *lsp_old, Word16 *lsfq, Decoder_State_fx *st, Word16 reset_q )
{
const Word16 *means;
Word16 lsf_old[M];
Word16 i;
means = PlcGetLsfBase ( st->lpcQuantization,
st->narrowBand,
st->sr_core );
Copy( st->lsf_old_fx, lsf_old, M );
modify_lsf( lsf_old, M, st->sr_core, reset_q );
lsf2lsp_fx( lsf_old, lsp_old, M, st->sr_core );
IF( reset_q )
{
FOR ( i=0; i<M; i++ )
{
lsfq[i] = add(st->mem_MA_fx[i], means[i]);
move16();
}
sort_fx( lsfq, 0, sub(M, 1) );
reorder_lsfs( lsfq, LSF_GAP_FX, M, st->sr_core );
lsf2lsp_fx( lsfq, lspq, M, st->sr_core );
}
ELSE
{
modify_lsf( lsfq, M, st->sr_core, reset_q );
lsf2lsp_fx(lsfq, lspq, M, st->sr_core);
}
return;
}
void modify_lsf(
Word16 *lsf,
const Word16 n,
const Word32 sr_core
, Word16 reset_q
)
{
Word16 i, k, th_x1p28_Q14;
Word16 gap, gap_sum;
th_x1p28_Q14 = 4864/*1900.0f*1.28f Q1*/;
move16();
if( L_sub( sr_core, 16000 ) == 0 )
{
th_x1p28_Q14 = 6080/*2375.0f*1.28f Q1*/;
move16();
}
IF( reset_q == 0 )
{
th_x1p28_Q14 = 2048; /* 800.0f*1.28f Q1*/ move16();
if( L_sub( sr_core, 16000 ) == 0 )
{
th_x1p28_Q14 = 2560; /*1000.0f*1.28f Q1*/ move16();
}
}
FOR ( i=1; i<n; i++)
{
IF ( sub(lsf[i], th_x1p28_Q14) >= 0 )
{
BREAK;
}
}
gap = mult_r(lsf[i - 1], InvIntTable[i]);
move16();
gap_sum = gap;
i = sub(i,1);
FOR(k = 0; k < i; k++)
{
move16();
lsf[k] = gap_sum;
gap_sum = add(gap_sum, gap);
}
}
static void reorder_lsfs(
Word16 *lsf, /* i/o: vector of lsfs in the frequency domain (0..0.5)*/
const Word16 min_dist0, /* i : minimum required distance */
const Word16 n, /* i : LPC order */
const Word32 sr_core /* i : input sampling frequency */
)
{
Word16 i;
Word16 curr_min_dist;
Word16 min_dist_fac2;
Word16 min_dist_fac3;
Word16 lsf_min;
Word16 lsf_max;
Word16 fs2;
Word16 th1, th2;
Word16 min_dist;
fs2 = 16384/*6400.0 * 1.28 Q1*/;
move16();
if(L_sub(sr_core, 16000) == 0)
{
fs2 = 20480/*8000.0 * 1.28 Q1*/;
move16();
}
/*-----------------------------------------------------------------*
* Verify the LSF ordering and minimum GAP
*-----------------------------------------------------------------*/
IF( L_sub( sr_core, 16000 )==0 )
{
th1 = 3200;
move16();
th2 = 6080;
move16();
min_dist = add( min_dist0, shr(min_dist0,2) );
}
ELSE
{
th1 = 2560;
move16();
th2 = 4864;
move16();
min_dist = min_dist0;
move16();
}
min_dist_fac2 = shl(min_dist, 1);
min_dist_fac3 = add(min_dist, min_dist_fac2);
curr_min_dist = min_dist_fac3;
move16();
lsf_min = curr_min_dist;
move16();
FOR (i = 0; i < n; i++)
{
IF (sub(lsf[i], th1) > 0)
{
curr_min_dist = min_dist_fac2;
move16();
}
ELSE
{
if (sub(lsf[i], th2) > 0)
{
curr_min_dist = min_dist;
move16();
}
}
if (sub(lsf[i], lsf_min) < 0)
{
lsf[i] = lsf_min;
move16();
}
lsf_min = add(lsf[i], curr_min_dist);
}
/*------------------------------------------------------------------------------------------*
* Reverify the LSF ordering and minimum GAP in the reverse order (security)
*------------------------------------------------------------------------------------------*/
lsf_max = sub(fs2, curr_min_dist);
IF (sub(lsf[n-1], lsf_max) > 0) /* If danger of unstable filter in case of resonance in HF */
{
FOR (i = sub(n, 1); i >= 0; i--) /* Reverify the minimum ISF gap in the reverse direction */
{
IF (sub(lsf[i], th2) <= 0)
{
curr_min_dist = min_dist_fac2;
move16();
}
ELSE
{
if (sub(lsf[i], th1) <= 0)
{
curr_min_dist = min_dist_fac3;
move16();
}
}
if (sub(lsf[i], lsf_max) > 0)
{
lsf[i] = lsf_max;
move16();
}
lsf_max = sub(lsf[i], curr_min_dist);
}
}
return;
}
+250
View File
@@ -0,0 +1,250 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "stl.h"
#include "prot_fx.h"
#include "basop_util.h"
#include "options.h"
#define HP20_COEFF_SCALE (2)
/*
* hp20
*
* Function:
* 2nd order high pass filter with nominal cut off frequency at 20 Hz.
*
* Returns:
* void
*/
static Word32 HP50_Mode2_Mpy_32_16_fix(Word32 a, Word16 b)
{
Word32 result = Mpy_32_16_1(a,b);
/* perform rounding towards lower value for negative results */
if (result < 0) result = L_add(result,1);
return result;
}
static Word32 HP50_Mpy_32_32_fix(Word32 a, Word32 b)
{
Word32 result = Mpy_32_32(a,b);
/* perform rounding towards lower value for negative results */
if (result < 0) result = L_add(result,1);
return result;
}
static void filter_2nd_order(
Word16 signal[],
const Word16 stride,
const Word16 prescale,
const Word16 lg,
Word32 mem[4],
Word32 a1,
Word32 a2,
Word32 b1,
Word32 b2
)
{
Word16 i;
Word16 x2, x1;
Word32 L_sum, L_y1, L_y2;
/*
* Saturation: The states of the filter, namely L_y1 and L_y2 shall
* never saturate, because that causes error in the filter feedback.
* The final output written into signal[] might saturate because of
* unavoidable filter overshoot.
*/
/* Execute first 2 iterations with 32-bit x anx y memory values */
BASOP_SATURATE_ERROR_ON
L_sum = HP50_Mpy_32_32_fix(b2,mem[2]); /* b2*x2 */
L_sum = L_add(L_sum,HP50_Mpy_32_32_fix(b1,mem[3])); /* b1*x1 */
x2 = shr(signal[0*stride], prescale);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x2)); /* b2*x0 */
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[0],a2)); /* y2*a2 */
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[1],a1)); /* y1*a1 */
L_y2 = L_shl(L_sum, HP20_COEFF_SCALE);
BASOP_SATURATE_ERROR_OFF
BASOP_SATURATE_WARNING_OFF
signal[0*stride] = round_fx(L_shl(L_y2, prescale));
BASOP_SATURATE_WARNING_ON
BASOP_SATURATE_ERROR_ON
L_sum = HP50_Mpy_32_32_fix(b2,mem[3]); /* b2*x2 */
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x2)); /* b1*x1 */
x1 = shr(signal[1*stride], prescale);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x1)); /* b2*x0 */
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[1],a2)); /* y2*a2 */
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2, a1)); /* y1*a1 */
L_y1 = L_shl(L_sum, HP20_COEFF_SCALE);
BASOP_SATURATE_ERROR_OFF
BASOP_SATURATE_WARNING_OFF
signal[1*stride] = round_fx(L_shl(L_y1, prescale));
BASOP_SATURATE_WARNING_ON
/* New we use a trick and toggle x1/x2 and L_y1/L_y2 to save a few cycles unrolling the loop by 2 */
FOR (i = 2; i < lg; i+=2)
{
/* y[i+0] = b2*x[i-2] + b1*x[i-1] + b2*x[i-0] + a2*y[i-2] + a1*y[i-1]; */
BASOP_SATURATE_ERROR_ON
L_sum = HP50_Mode2_Mpy_32_16_fix(b2,x2);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x1));
x2 = shr(signal[i*stride], prescale);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x2));
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2,a2));
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y1,a1));
L_y2 = L_shl(L_sum, HP20_COEFF_SCALE);
BASOP_SATURATE_ERROR_OFF
BASOP_SATURATE_WARNING_OFF
signal[i*stride] = round_fx(L_shl(L_y2, prescale));
BASOP_SATURATE_WARNING_ON
/* y[i+1] = b2*x[i-1] + b1*x[i-0] + b2*x[i+1] + a2*y[i-1] + a1*y[i+0]; */
BASOP_SATURATE_ERROR_ON
L_sum = HP50_Mode2_Mpy_32_16_fix(b2,x1);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x2));
x1 = shr(signal[(i+1)*stride], prescale);
L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x1));
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y1,a2));
L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2,a1));
L_y1 = L_shl(L_sum, HP20_COEFF_SCALE);
BASOP_SATURATE_ERROR_OFF
BASOP_SATURATE_WARNING_OFF
signal[(i+1)*stride] = round_fx(L_shl(L_y1, prescale));
BASOP_SATURATE_WARNING_ON
}
/* update static filter memory from variables */
mem[0] = L_y2;
move32();
mem[1] = L_y1;
move32();
mem[2] = L_deposit_h(x2);
mem[3] = L_deposit_h(x1);
return;
}
void hp20(Word16 signal[], /* i/o: signal to filter any */
const Word16 stride, /* i : stride to be applied accessing signal */
const Word16 lg, /* i : length of signal (integer) Q0 */
Word32 mem[5], /* i/o: static filter memory with this layout: */
/* mem[0]: y[-2] (32-bit) */
/* mem[1]; y[-1] (32-bit) */
/* mem[2]: x[-2] << 16 */
/* mem[3]: x[-1] << 16 */
/* Note: mem[0..3] need to be scaled per frame */
/* mem[4]: states scale */
const Word32 sFreq) /* i : input sampling rate Q0 */
{
Word32 a1, b1, a2, b2;
Word16 prescale, prescaleOld, diff;
prescale = getScaleFactor16(signal, lg);
prescaleOld = extract_l(mem[4]);
diff = norm_l(L_shl(mem[2], prescaleOld));
if (mem[2] != 0)
{
prescale = s_min(prescale, diff);
}
diff = norm_l(L_shl(mem[3], prescaleOld));
if (mem[3] != 0)
{
prescale = s_min(prescale, diff);
}
/* Take into account the left shift performed into the loop + 1 bit headroom*/
prescale = s_max(-12, sub(1+HP20_COEFF_SCALE, prescale));
IF (prescale != prescaleOld)
{
diff = sub(prescale, prescaleOld);
mem[0] = L_shr(mem[0], diff);
move32();
mem[1] = L_shr(mem[1], diff);
move32();
mem[2] = L_shr(mem[2], diff);
move32();
mem[3] = L_shr(mem[3], diff);
move32();
mem[4] = L_deposit_l(prescale);
}
IF ( L_sub(sFreq,8000) == 0 )
{
/* hp filter 20Hz at 3dB for 8000 Hz input sampling rate
[b,a] = butter(2, 20.0/4000.0, 'high');
b = [0.988954248067140 -1.977908496134280 0.988954248067140]
a = [1.000000000000000 -1.977786483776764 0.978030508491796]*/
a1 = L_add(0,1061816033l/* 1.977786483776764 Q29*/);
a2 = L_add(0,-525076131l/*-0.978030508491796 Q29*/);
b1 = L_add(0,-1061881538l/*-1.977908496134280 Q29*/);
b2 = L_add(0,530940769l/* 0.988954248067140 Q29*/);
}
ELSE IF ( L_sub(sFreq,16000) == 0 )
{
/* hp filter 20Hz at 3dB for 16000KHz sampling rate
[b,a] = butter(2, 20.0/8000.0, 'high');
b = [0.994461788958195 -1.988923577916390 0.994461788958195]
a = [1.000000000000000 -1.988892905899653 0.988954249933127] */
a1 = L_add(0,1067778748l/* 1.988892905899653 Q29*/);
a2 = L_add(0,-530940770l/*-0.988954249933127 Q29*/);
b1 = L_add(0,-1067795215l/*-1.988923577916390 Q29*/);
b2 = L_add(0,533897608l/* 0.994461788958195 Q29*/);
}
ELSE IF ( L_sub(sFreq,32000) == 0 )
{
/* hp filter 20Hz at 3dB for 32000KHz sampling rate
[b,a] = butter(2, 20.0/16000.0, 'high');
b = [0.997227049904470 -1.994454099808940 0.997227049904470]
a = [1.000000000000000 -1.994446410541927 0.994461789075954]*/
a1 = L_add(0,1070760263l/* 1.994446410541927 Q29*/);
a2 = L_add(0,-533897608l/*-0.994461789075954 Q29*/);
b1 = L_add(0,-1070764392l/*-1.994454099808940 Q29*/);
b2 = L_add(0,535382196l/* 0.997227049904470 Q29*/);
}
ELSE
{
assert (sFreq == 48000);
/* hp filter 20Hz at 3dB for 48000KHz sampling rate
[b,a] = butter(2, 20.0/24000.0, 'high');
b =[0.998150511190452 -1.996301022380904 0.998150511190452]
a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
a1 = L_add(0,1071754114l/* 1.996297601769122 Q29*/);
a2 = L_add(0,-534886875l/*-0.996304442992686 Q29*/);
b1 = L_add(0,-1071755951l/*-1.996301022380904 Q29*/);
b2 = L_add(0,535877975l/* 0.998150511190452 Q29*/);
}
filter_2nd_order(signal,
stride,
prescale,
lg,
mem,
a1,
a2,
b1,
b2);
return;
}
+912
View File
@@ -0,0 +1,912 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "prot_fx.h"
#include "stl.h" /* required for wmc_tool */
#define MIN_BITS_FIX 0 /* QRk=18 */
#define HQ_16k40_BIT (HQ_16k40/50) /* 16400/50=328 */
#define Qbf 14 /* Q value for bits_fact */
#define C1_QRk (1<<SWB_BWE_LR_QRk) /* 1 */
#define C1_Qbf (1<<Qbf) /* 1 */
#define BITS_FACT_1p10 18022 /* (Word16)(1.10f*(float)pow(2, Qbf)+0.5f) */
#define BITS_FACT_1p05 17203 /* (Word16)(1.05f*(float)pow(2, Qbf)+0.5f) */
#define BITS_FACT_1p00 16384 /* (Word16)(1.00f*(float)pow(2, Qbf)+0.5f) */
#define BITS_FACT_0p97 15892 /* (Word16)(0.97f*(float)pow(2, Qbf)+0.5f) */
#define BITS_FACT_0p92 15073 /* (Word16)(0.92f*(float)pow(2, Qbf)+0.5f) */
/*-------------------------------------------------------------------*
* Bits2indvsb()
*
* Bit allocation to individual SB's in a group
*-------------------------------------------------------------------*/
void Bits2indvsb_fx (
const Word32 *L_be, /* i : Qbe Band Energy of sub-band */
const Word16 start_band, /* i : Q0 start band indices */
const Word16 end_band, /* i : Q0 end band indices */
const Word16 Bits, /* i : Q0 Total number of bits allocated to a group */
const Word32 L_Bits_needed, /* i : QRk smallest bit number for allocation in group */
Word32 *L_Rsubband, /* o : QRk bit allocation of sub-band */
Word16 *p2aflags_fx /* i/o: Q0 peaky/noise subband flag */
)
{
Word16 i,j,k;
Word32 L_R_temp[14]; /* QRk = QL_Rsubband; */
Word16 Ravg_fx;
Word16 QRavg;
const Word32 *L_y_ptr;
Word32 *L_R_ptr;
Word16 Bits_avg_fx;
Word16 QBavg;
Word16 scale_fact_fx;
Word16 band_num_fx;
Word16 index_fx[14];
Word16 y_index_fx[14];
Word16 be_sum_fx; /* Q0 */
Word16 exp_normn, exp_normd;
Word16 enr_diffcnt_fx;
Word16 th_5_fx;
Word16 Rcnt_fx;
Word16 be_cnt_fx;
Word16 *p2aflags_fx_ptr;
Word32 L_temp1;
Word32 L_temp2;
band_num_fx = sub(end_band, start_band);
L_y_ptr = L_be + start_band;
L_R_ptr = L_Rsubband + start_band;
p2aflags_fx_ptr = p2aflags_fx+start_band;
FOR ( i = 0; i < band_num_fx; i++ )
{
y_index_fx[i] = extract_h(L_shr(L_y_ptr[i], sub(SWB_BWE_LR_Qbe,16)));
index_fx[i] = i;
move16();
}
/* Rearrange norm vector in decreasing order */
reordvct_fx(y_index_fx, band_num_fx, index_fx);
be_sum_fx = 0;
move16();
be_cnt_fx = 0;
move16();
FOR( j=0; j<band_num_fx; j++ )
{
test();
IF ( y_index_fx[j] <= 0 || p2aflags_fx_ptr[index_fx[j]] == 0 )
{
y_index_fx[j] = 0;
move16();
L_R_temp[j] = L_deposit_l(0);
}
ELSE
{
L_R_temp[j] = C1_QRk;
move32(); /* filled not zero value */
be_cnt_fx = add(be_cnt_fx, 1);
}
}
i = sub(be_cnt_fx, 1);
FOR(k = 0; k <=i ; k++)
{
if( L_R_temp[k] > 0 )
{
be_sum_fx = add(be_sum_fx, y_index_fx[k]);
}
}
QBavg = 0;
move16();
/*Ravg = (float) be_sum/be_cnt;*/
Ravg_fx = 0;
move16();
QRavg = 0;
move16();
IF( be_cnt_fx != 0x0 )
{
exp_normn = norm_s(be_sum_fx);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(be_cnt_fx);
Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(be_cnt_fx, exp_normd));
Ravg_fx = shr(Ravg_fx, 2); /* safe shift */
QRavg = add(sub(exp_normn, exp_normd), 15-2);
}
enr_diffcnt_fx = 0;
move16();
th_5_fx = shl(5, QRavg);
FOR (j = 0; j < be_cnt_fx; j++)
{
if( sub(abs_s(sub(Ravg_fx, shl(y_index_fx[j], QRavg))), th_5_fx) > 0 )
{
enr_diffcnt_fx = add(enr_diffcnt_fx, 1);
}
}
scale_fact_fx = 19661;
move16(); /* 0.60f 19660.8(Q15) */
if( enr_diffcnt_fx > 0 )
{
scale_fact_fx = 11468;
move16(); /* 0.35f 11468.8(Q15) */
}
/* Bits allocation to individual SB's in a group based on Band Energies */
FOR (j = 0; j < be_cnt_fx; j++)
{
Rcnt_fx = add(i, 1);
/* Ravg = (float) be_sum/Rcnt; */
exp_normn = norm_s(be_sum_fx);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(Rcnt_fx);
Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(Rcnt_fx, exp_normd));
Ravg_fx = shr(Ravg_fx, 2); /* safe shift */
QRavg = add(sub(exp_normn, exp_normd), 15-2);
if(be_sum_fx <= 0)
{
be_sum_fx = 1;
move16();
}
/* Bits_avg = (float) Bits/(be_sum+EPSILON); */
Bits_avg_fx = 0;
move16();
QBavg = 0;
move16();
IF ( Bits != 0 )
{
exp_normn = norm_s(Bits);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(be_sum_fx);
Bits_avg_fx = div_s(shl(Bits, exp_normn), shl(be_sum_fx, exp_normd));
Bits_avg_fx = shr(Bits_avg_fx, 2); /* safe_shift */
QBavg = add(sub(exp_normn, exp_normd), 15-2);
}
FOR (k = 0; k <=i; k++)
{
IF(L_R_temp[k] > 0) /* Rtemp -> SWB_BWE_LR_QRk */
{
/* Allocate more bits to SB, if SB bandenergy is higher than average energy */
/* R_temp[k] = (float)( Bits_avg * y_index[k]+( scale_fact * (y_index[k] - Ravg))); */
L_temp1 = L_mult(Bits_avg_fx, y_index_fx[k]); /* QBavg+1 */
L_temp2 = L_mult(scale_fact_fx, sub(shl(y_index_fx[k], QRavg), Ravg_fx)); /* 15+QRavg+1 */
L_R_temp[k] = L_add(L_shr(L_temp1, sub(add(QBavg, 1), SWB_BWE_LR_QRk)), L_shr(L_temp2, sub(add(QRavg, 16), SWB_BWE_LR_QRk))); /* SWB_BWE_LR_QRk */
}
}
IF ( L_sub(L_R_temp[i], L_Bits_needed) < 0 )
{
L_R_temp[i] = L_deposit_l(0);
p2aflags_fx_ptr[index_fx[i]] = 0;
move16();
/* be_sum -= y_index[i]; */
be_sum_fx = sub(be_sum_fx, y_index_fx[i]);
i = sub(i, 1);
}
ELSE
{
BREAK;
}
}
/* Rearrange the bit allocation to align with original */
FOR ( k = 0 ; k < band_num_fx; k++ )
{
j = index_fx[k];
move16();
L_R_ptr[j] = L_R_temp[k];
move32();
}
return;
}
/*-------------------------------------------------------------------*
* hq2_bit_alloc_har()
*
* Bit allocation mechanism for HQ_HARMONIC mode
*-------------------------------------------------------------------*/
void hq2_bit_alloc_har_fx (
const Word32 *L_y, /* i : Qbe band energy of sub-vectors */
Word16 B_fx, /* i : Q0 number of available bits */
const Word16 N_fx, /* i : Q0 number of sub-vectors */
Word32 *L_Rsubband, /* o : QRk sub-band bit-allocation vector */
Word16 p2a_bands_fx, /* i : highfreq bands */
const Word32 L_core_brate, /* i : Q0 core bit rate */
Word16 p2a_flags_fx[], /* i/o: Q0 p2a_flags */
const Word16 band_width_fx[] /* i : Q0 table of band_width */
)
{
Word16 i, j, k;
Word32 L_norm_sum; /* Qbe */
Word32 L_Ravg_sub[GRP_SB]; /* Qbe */
Word32 L_temp_band_energy[BANDS_MAX]; /* Qbe */
Word16 j_fx, k_fx, Bits_grp_fx[GRP_SB];
Word32 L_temp_band_energydiff[BANDS_MAX];
Word16 G1_BE_DIFF_POS_fx; /* Q0 */
Word32 L_G1_BE_DIFF_VAL; /* Qbe Word32 */
Word16 final_gr_fact_pos_fx, gmax_range_fx[2], temp_fx;
Word16 bits_fact_fx, bits_fact1_fx; /* Q? */
Word16 grp_rngmax_fx[2] = {0};
Word16 index_fx[NB_SWB_SUBBANDS_HAR], y_index_fx[NB_SWB_SUBBANDS_HAR], esthf_bits_fx, grp_bit_avg_fx, harmonic_band_fx;
Word32 L_norm_sum_avg;
Word32 L_norm_diff; /* Qbe */
Word16 bits_allocweigh_fx; /* Q15 */
Word16 grp_bound_fx[5];
Word32 L_grp_thr[GRP_SB]; /* not require Word32 precission */
Word16 lf_hf_ge_r_fx; /* Q15 */
Word32 L_avg_enhf_en_diff; /* Qbe */
Word16 B_norm_fx;
Word32 L_temp, L_temp2;
Word16 exp, frac;
Word32 L_THR1, L_THR2, L_THR3;
Word16 exp_norm;
Word16 norm_sum_fx;
Word16 Qns; /* Q value for norm_sum_fx */
Word16 Inv_norm_sum_fx; /* 1/norm_sum */
Word16 QIns; /* Q value for Inv_norm_sum_fx */
Word16 exp_normn, exp_normd;
Word16 div_fx;
Word16 Inv_p2a_bands_fx;
Word16 QIpb;
Word16 exp_shift;
L_THR1 = L_shl(L_deposit_l(THR1), SWB_BWE_LR_QRk);
L_THR2 = L_shl(L_deposit_l(THR2), SWB_BWE_LR_QRk);
L_THR3 = L_shl(L_deposit_l(THR3), SWB_BWE_LR_QRk);
set16_fx(Bits_grp_fx, 0, GRP_SB);
/* Initialize subbands bits allocation vector based on harmonic bands */
harmonic_band_fx = add(sub(N_fx, p2a_bands_fx), 1);
/*printf("harmonic_band= %d %d\n", harmonic_band, harmonic_band_fx);*/
FOR (k = 0; k < N_fx; k++)
{
L_Rsubband[k] = (Word32)(C1_QRk);
move32(); /* Constant Value */
L_temp_band_energy[k] = L_y[k];
move32(); /* SWB_BWE_LR_Qbe */
}
final_gr_fact_pos_fx = 2;
move16();
bits_fact_fx = C1_Qbf;
move16();
bits_fact1_fx = C1_Qbf;
move16();
gmax_range_fx[0]= G1_RANGE;
move16();
gmax_range_fx[1]= G1G2_RANGE;
move16();
IF( L_sub(L_core_brate, HQ_16k40) == 0 )
{
gmax_range_fx[1] = add(gmax_range_fx[1], 2);
move16();
}
/* decide each group range, for grouping spectral coefficients */
grp_rngmax_fx[1] = 16;
move16();
grp_rngmax_fx[0] = 7;
move16();
temp_fx = 0;
move16();
FOR( i=0; i<2; i++ )
{
j_fx = gmax_range_fx[i];
move16();
k_fx = 0;
move16();
WHILE( L_sub(L_temp_band_energy[gmax_range_fx[i]-1], L_temp_band_energy[j_fx] ) >= 0x0L && sub(j_fx, grp_rngmax_fx[i]) < 0x0 )
{
test();
k_fx = add(k_fx, 1);
j_fx = add(j_fx, 1);
}
temp_fx = k_fx;
move16();
IF( sub(temp_fx, 1) > 0 )
{
FOR( temp_fx = 2; temp_fx <= k_fx ; )
{
IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) < 0 )
{
BREAK;
}
ELSE IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) >= 0 )
{
temp_fx = add(temp_fx, 1);;
IF( sub(temp_fx, k_fx) > 0 )
{
temp_fx = sub(temp_fx, 1);
BREAK;
}
}
}
gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx);
move16();
}
ELSE
{
gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx);
move16();
}
}
grp_bound_fx[0] = 0;
move16();
FOR(i=1; i<GRP_SB-1; i++)
{
grp_bound_fx[i] = gmax_range_fx[i-1];
move16();
}
grp_bound_fx[i] = harmonic_band_fx;
move16();
grp_bound_fx[i+1] = N_fx;
move16();
FOR(i=0; i<GRP_SB; i++)
{
L_Ravg_sub[i] = L_deposit_l(0);
FOR ( j = grp_bound_fx[i]; j < grp_bound_fx[i+1]; j++ )
{
IF ( L_temp_band_energy[j] > 0x0L )
{
L_Ravg_sub[i] = L_add(L_Ravg_sub[i], L_temp_band_energy[j]);
move32();
}
}
}
L_temp_band_energydiff[0] = L_temp_band_energy[0];
move32();
FOR ( j = 1; j < harmonic_band_fx; j++ )
{
L_temp_band_energydiff[j]= L_abs(L_sub(L_temp_band_energy[j], L_temp_band_energy[j-1]));
move32();
}
G1_BE_DIFF_POS_fx = 0;
move16();
L_G1_BE_DIFF_VAL = L_deposit_l(0);
FOR(j=1; j< harmonic_band_fx; j++)
{
IF( L_sub(L_temp_band_energydiff[j], L_G1_BE_DIFF_VAL) > 0 )
{
G1_BE_DIFF_POS_fx = j;
move16();
L_G1_BE_DIFF_VAL = L_add(0,L_temp_band_energydiff[j]);
}
}
test();
test();
IF( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0] ) < 0 && G1_BE_DIFF_POS_fx > 0 )
{
final_gr_fact_pos_fx = 0;
move16();
}
ELSE IF ( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0]) >= 0 && sub(G1_BE_DIFF_POS_fx, gmax_range_fx[1] ) < 0 )
{
final_gr_fact_pos_fx = 1;
move16();
}
ELSE
{
final_gr_fact_pos_fx = 2;
move16();
}
test();
IF( final_gr_fact_pos_fx == 0 || sub(final_gr_fact_pos_fx, 1) == 0 )
{
IF( L_sub(L_core_brate, HQ_16k40 ) == 0 )
{
bits_fact_fx = BITS_FACT_1p10;
move16(); /* 1.10f; */ /* G1 */
bits_fact1_fx = BITS_FACT_0p92;
move16(); /* 0.92f; */ /* G3 */
}
ELSE
{
bits_fact_fx = BITS_FACT_1p05;
move16(); /* 1.05f; */ /* G1 */
bits_fact1_fx = BITS_FACT_0p97;
move16(); /* 0.97f; */ /* G3 */
}
}
ELSE
{
IF( L_sub(L_core_brate, HQ_16k40) == 0 )
{
bits_fact_fx = BITS_FACT_0p97;
move16(); /* 0.97f; */ /* G1 */
bits_fact1_fx = BITS_FACT_1p00;
move16(); /* 1.00f; */ /* G3 */
}
ELSE
{
bits_fact_fx = BITS_FACT_0p92;
move16(); /* 0.92f; */ /* G1 */
bits_fact1_fx = BITS_FACT_1p00;
move16(); /* 1.00f; */ /* G3 */
}
}
j = sub(N_fx, harmonic_band_fx);
FOR ( i = 0; i < j; i++ )
{
y_index_fx[i] = extract_h(L_shl(L_temp_band_energy[harmonic_band_fx+i], sub(16, SWB_BWE_LR_Qbe)));
index_fx[i] = add(harmonic_band_fx, i);
move16();
}
reordvct_fx(y_index_fx, sub(N_fx, harmonic_band_fx), index_fx);
/* Log2 */
L_temp = L_deposit_l(band_width_fx[index_fx[0]]);
exp = norm_l(L_temp);
frac = Log2_norm_lc(L_shl(L_temp, exp));
exp = sub(30, exp);
L_temp = L_Comp(exp, frac);
/* ceil */
if( L_and(0x0000ffff, L_temp) > 0 )
{
L_temp = L_add(L_temp, 0x00010000);
}
esthf_bits_fx = extract_h(L_temp);
L_grp_thr[0] = L_THR1;
move32();
L_grp_thr[1] = L_THR2;
move32();
L_grp_thr[2] = L_THR3;
move32();
L_grp_thr[3] = L_shl(L_deposit_l(esthf_bits_fx), SWB_BWE_LR_QRk);
move16();
L_norm_sum = L_deposit_l(1);
FOR(i=0; i<3; i++)
{
L_norm_sum = L_add( L_norm_sum, L_Ravg_sub[i]);
}
/*reserve bits for HF coding */
L_temp = L_add(L_norm_sum, L_Ravg_sub[GRP_SB-1]);
exp_normn = norm_l(L_temp);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(N_fx);
div_fx = div_l(L_shl(L_temp, exp_normn), shl(N_fx, exp_normd)); /* (Qbe+exp_normn)-(0+exp_normd)-1) */
L_norm_sum_avg = L_shr(L_deposit_h(div_fx), add(sub(exp_normn, exp_normd), 15)); /* -> Qbe */
exp_norm = norm_l(L_norm_sum);
norm_sum_fx = extract_h( L_shl(L_norm_sum, exp_norm) ); /* SWB_BWE_LR_Qbe+exp_norm-16 */
Qns = sub(add(SWB_BWE_LR_Qbe, exp_norm), 16);
Inv_norm_sum_fx = div_s( 0x4000 /* Q15 */ , norm_sum_fx );
QIns = sub(31, exp_norm); /* 14 - (14+exp_norm-16) + 15 */
grp_bit_avg_fx = div_s_ss(B_fx, GRP_SB); /* Q0 */
exp_normd = norm_s(p2a_bands_fx);
Inv_p2a_bands_fx = div_s(0x3fff, shl(p2a_bands_fx, exp_normd)); /* 14-exp_normd+15 */
QIpb = sub(29, exp_normd);
L_temp = L_shl(Mult_32_16(L_Ravg_sub[GRP_SB-1], Inv_p2a_bands_fx), sub(SWB_BWE_LR_Qbe, sub(QIpb,1)));
L_norm_diff = L_sub(L_temp, L_norm_sum_avg); /* Qbe */
L_temp = Mult_32_16(L_Ravg_sub[GRP_SB-1], sub(GRP_SB, 1)); /* Qbe+0+1 */
L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); /* Qbe+1+QIpb+1 */
lf_hf_ge_r_fx = round_fx(L_shl(L_temp, sub(15+16, sub(add(SWB_BWE_LR_Qbe, QIns),30))));
exp_normn = norm_s(norm_sum_fx);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(harmonic_band_fx);
div_fx = div_s(shl(norm_sum_fx, exp_normn), shl(harmonic_band_fx, exp_normd));
L_avg_enhf_en_diff = L_sub(L_temp_band_energy[index_fx[0]], L_shl(L_deposit_h(div_fx), sub(sub(SWB_BWE_LR_Qbe, (add(Qns,sub(exp_normn,exp_normd)))),31))); /* Qbe - (Qns+exp_normn-(exp_normd)+15) -16 */
test();
IF( sub(lf_hf_ge_r_fx , 26214) > 0x0 && L_sub(L_avg_enhf_en_diff, (Word32)(8<<SWB_BWE_LR_Qbe)) > 0x0L) /* 0.8=26214.4(Q15) 8.0f=131072(Qbe) */
{
bits_allocweigh_fx = 6554;
move16(); /* 0.2 6553.6(Q15) */
if(L_norm_diff < 0x0L)
{
bits_allocweigh_fx = 13107;
move16(); /* 0.4 13107.2(Q15) */
}
/*allocate bits*/
/*Bits_grp[GRP_SB-1] = (short)min((grp_bit_avg/p2a_bands + bits_allocweigh*norm_diff),10);*/
L_temp = L_mult(grp_bit_avg_fx, Inv_p2a_bands_fx); /* Q0+QIpb+1 */
L_temp2 = Mult_32_16(L_norm_diff, bits_allocweigh_fx); /* Qbe+Q15-15 */
L_temp = L_shr(L_temp, add(QIpb, 1));
L_temp = L_add(L_shl(L_temp,SWB_BWE_LR_Qbe), L_temp2);
Bits_grp_fx[GRP_SB-1] = extract_h(L_shl(L_temp, sub(16, SWB_BWE_LR_Qbe)));
Bits_grp_fx[GRP_SB-1] = s_min(Bits_grp_fx[GRP_SB-1], 10);
move16();
if( sub(Bits_grp_fx[GRP_SB-1], esthf_bits_fx) < 0 )
{
Bits_grp_fx[GRP_SB-1] = 0;
move16();
}
B_fx = sub(B_fx, Bits_grp_fx[GRP_SB-1]);
}
exp_shift = sub(add(SWB_BWE_LR_Qbe, QIns), 47); /* (SWB_BWE_LR_Qbe+14+1+QIns-15-16) */
exp_norm = norm_s(B_fx);
B_norm_fx = shl(B_fx, exp_norm);
exp_shift = add(exp_shift, exp_norm);
IF( sub(final_gr_fact_pos_fx, 1) == 0 )
{
L_temp = Mult_32_16(L_Ravg_sub[1], extract_h(L_mult(bits_fact_fx, B_norm_fx)));
L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx);
Bits_grp_fx[1] = extract_h(L_shr(L_temp, exp_shift));
L_temp = Mult_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx)));
L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx);
Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift));
Bits_grp_fx[0] = sub(sub(B_fx, Bits_grp_fx[1]), Bits_grp_fx[2]);
move16();
}
ELSE
{
L_temp = Mult_32_16(L_Ravg_sub[0], extract_h(L_mult(bits_fact_fx, B_norm_fx)));
L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx);
Bits_grp_fx[0] = extract_h(L_shr(L_temp, exp_shift));
L_temp = Mult_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx)));
L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx);
Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift));
Bits_grp_fx[1] = sub(sub(B_fx, Bits_grp_fx[0]), Bits_grp_fx[2]);
move16();
}
IF( sub(Bits_grp_fx[2], THR2 ) < 0 )
{
Bits_grp_fx[1] = add(Bits_grp_fx[1], Bits_grp_fx[2]);
move16();
Bits_grp_fx[2] = 0;
move16();
}
FOR(i=0; i<GRP_SB; i++)
{
IF(Bits_grp_fx[i] > 0)
{
Bits2indvsb_fx( L_temp_band_energy, grp_bound_fx[i], grp_bound_fx[i+1] , Bits_grp_fx[i], L_grp_thr[i], L_Rsubband, p2a_flags_fx);
}
ELSE
{
set32_fx(L_Rsubband+grp_bound_fx[i], 0x0L, sub(grp_bound_fx[i+1], grp_bound_fx[i]));
IF( sub(i, GRP_SB-1) == 0 )
{
set16_fx(p2a_flags_fx+grp_bound_fx[i], 0, sub(grp_bound_fx[i+1], grp_bound_fx[i]));
}
}
}
return;
}
/*--------------------------------------------------------------------------*
* hq2_bit_alloc()
*
* HQ2 bit-allocation
*--------------------------------------------------------------------------*/
Word32 hq2_bit_alloc_fx (
const Word32 L_band_energy[], /* i : band energy of each subband */
const Word16 bands, /* i : total number of subbands in a frame */
Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */
Word16 *bit_budget_fx, /* i/o: bit bugdet */
Word16 *p2a_flags, /* i : HF tonal indicator */
const Word16 weight_fx, /* i : weight */
const Word16 band_width[], /* i : Sub band bandwidth */
const Word16 num_bits, /* i : available bits */
const Word16 hqswb_clas, /* i : HQ2 class information */
const Word16 bwidth, /* i : input bandwidth */
const Word16 is_transient /* i : indicator HQ_TRANSIENT or not */
)
{
Word16 j, k;
Word16 tmp;
Word16 bit_budget_norm_fx;
Word32 L_Rcalc, L_Ravg, L_Rcalc1;
Word16 exp_normn, exp_normd;
Word16 Rcnt_fx;
Word16 div_fx;
Word16 Qdiv;
Word32 L_tmp;
Word16 tmp_fx;
Word32 L_maxxy;
Word16 maxdex_fx;
Word32 L_dummy;
Word16 bit_budget_temp_fx;
Word16 negflag;
Word32 L_THR1, L_THR2, L_THR3;
L_THR1 = L_shl(L_deposit_l(THR1), SWB_BWE_LR_QRk);
L_THR2 = L_shl(L_deposit_l(THR2), SWB_BWE_LR_QRk);
L_THR3 = L_shl(L_deposit_l(THR3), SWB_BWE_LR_QRk);
/* Init Rk to non-zero values for bands to be allocated bits */
IF( sub(num_bits, HQ_16k40_BIT) <= 0 )
{
set32_fx( L_Rk, (Word32)(C1_QRk), bands); /* 1<<SWB_BWE_LR_QRk */
test();
IF( is_transient && sub(bands, 32) == 0 )
{
L_Rk[6] = L_deposit_l(0);
L_Rk[7] = L_deposit_l(0);
L_Rk[14] = L_deposit_l(0);
L_Rk[15] = L_deposit_l(0);
L_Rk[22] = L_deposit_l(0);
L_Rk[23] = L_deposit_l(0);
L_Rk[30] = L_deposit_l(0);
L_Rk[31] = L_deposit_l(0);
}
}
ELSE
{
/*mvs2r( p2a_flags, Rk, bands ); */
FOR(k=0; k<bands; k++)
{
L_Rk[k] = L_shl(L_deposit_l(p2a_flags[k]), SWB_BWE_LR_QRk);
}
}
L_Rcalc = L_deposit_l(0);
L_Rcalc1 = L_deposit_l(0);
FOR (j = 0; j < bands; j++)
{
Rcnt_fx = 0;
move16();
L_Ravg = L_add(0,0x0L);
FOR (k = 0; k < bands; k++)
{
IF ( L_Rk[k] > 0 )
{
L_Ravg = L_add(L_Ravg, L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe))); /* SWB_BWE_LR_QRk-SWB_BWE_LR_Qbe */
Rcnt_fx = add(Rcnt_fx, 1);
}
}
/* Ravg Qband_energy */
/*L_Ravg /= Rcnt; */
exp_normd = norm_l(L_Ravg);
exp_normd = sub(exp_normd, 1);
exp_normn = norm_s(Rcnt_fx);
tmp = shl(Rcnt_fx, exp_normn);
tmp = s_max(tmp,1);
IF ( L_Ravg > 0 )
{
div_fx = div_l(L_shl(L_Ravg, exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */
}
ELSE
{
div_fx = div_l(L_shl(L_abs(L_Ravg), exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */
div_fx = negate(div_fx);
}
Qdiv = sub(sub(add(SWB_BWE_LR_QRk, exp_normd), exp_normn), 1);
L_Ravg = L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk));
exp_normd = norm_s(*bit_budget_fx);
exp_normd = sub(exp_normd, 1);
bit_budget_norm_fx = shl(*bit_budget_fx, exp_normd);
div_fx = 0;
move16();
test();
IF( bit_budget_norm_fx > 0 && sub(bit_budget_norm_fx, tmp) < 0 )
{
div_fx = div_s(bit_budget_norm_fx, tmp);
}
Qdiv = add(sub(exp_normd, exp_normn), 15);
FOR (k = 0; k < bands; k++)
{
IF ( L_Rk[k] > 0)
{
/*Rk[k] = ((float) *bit_budget / Rcnt + weight * (band_energy[k] - Ravg)); */
L_tmp = Mult_32_16(L_sub(L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe)), L_Ravg), weight_fx); /* SWB_BWE_LR_QRk + Q13 - 15 */
L_tmp = L_shl(L_tmp, 2); /* -> SWB_BWE_LR_QRk */
L_Rk[k] = L_add(L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk)) , L_tmp);
move32();
}
}
negflag = 0;
move16();
L_Rcalc = L_deposit_l(0);
FOR (k = 0; k < bands; k++)
{
IF ( L_sub(L_Rk[k], MIN_BITS_FIX) < 0 )
{
L_Rk[k] = L_deposit_l(0);
negflag = 1;
move16();
}
L_Rcalc = L_add( L_Rcalc , L_Rk[k]); /*SWB_BWE_LR_QRk */
}
/* prune noiselike bands with low allocation */
test();
IF ( sub(num_bits, HQ_16k40_BIT) <= 0 && negflag == 0)
{
L_maxxy = L_deposit_l(0);
maxdex_fx = -1;
move16();
L_Rcalc = L_deposit_l(0);
/* find worst under-allocation */
FOR (k = sub(bands, 1); k >= 0; k--)
{
tmp_fx = s_min( band_width[k], s_max(12, shr( band_width[k], 2)));
L_dummy = L_sub(L_shl(L_deposit_l(tmp_fx), SWB_BWE_LR_QRk), L_Rk[k]) ; /*SWB_BWE_LR_QRk */
test();
test();
IF ( p2a_flags[k] == 0 && L_sub(L_dummy, L_maxxy) > 0 && L_Rk[k] > 0 )
{
maxdex_fx = k;
move16();
L_maxxy = L_add(0,L_dummy); /*SWB_BWE_LR_QRk */
}
}
/* prune worst allocation and recalculate total allocation */
if ( sub(maxdex_fx, -1) > 0)
{
L_Rk[maxdex_fx] = L_deposit_l(0);
}
FOR (k = 0; k < bands; k++)
{
L_Rcalc = L_add(L_Rcalc, L_Rk[k]); /*SWB_BWE_LR_QRk */
}
}
test();
test();
IF ( L_sub(L_Rcalc, L_Rcalc1) == 0 && sub(bwidth, SWB) == 0 )
{
/* Reallocate bits to individual subbands for HQ_NORMAL mode */
/* if bits allocated to subbands areless than predefined threshold */
test();
IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0 )
{
L_dummy = L_deposit_l(0);
FOR( k = 0; k < bands; k++ )
{
test();
test();
test();
test();
test();
IF( sub(k, 11) < 0 && L_sub(L_Rk[k], L_THR1) < 0 )
{
L_Rk[k] = L_deposit_l(0);
}
ELSE IF( sub(k, 11) >= 0 && sub(k, 16) < 0 && L_sub(L_Rk[k], L_THR2) < 0 )
{
L_Rk[k] = L_deposit_l(0);
}
ELSE if( sub(k, 16) >= 0 && sub(k, bands ) < 0 && L_sub(L_Rk[k], L_THR3) < 0 )
{
L_Rk[k] = L_deposit_l(0);
}
L_dummy = L_add(L_dummy, L_Rk[k]);
}
IF( L_sub(L_dummy, L_Rcalc ) == 0 )
{
test();
IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0)
{
bit_budget_temp_fx = *bit_budget_fx;
move16();
FOR( k=0; k<NB_SWB_SUBBANDS; k++ )
{
test();
IF( p2a_flags[bands-NB_SWB_SUBBANDS+k] == 1 && L_Rk[bands-NB_SWB_SUBBANDS+k] == 0 )
{
p2a_flags[bands-NB_SWB_SUBBANDS+k] = 0;
move16();
bit_budget_temp_fx = sub(bit_budget_temp_fx, bits_lagIndices_modeNormal_fx[k]);
}
}
IF( sub(bit_budget_temp_fx, *bit_budget_fx ) < 0)
{
*bit_budget_fx = bit_budget_temp_fx;
move16();
/* a negative *bit_budget_fx may occur here due to Bit Errors */
/* handled outside this function to properly set flag: st_fx->BER_detect */
}
ELSE IF( sub(bit_budget_temp_fx, *bit_budget_fx ) == 0 )
{
BREAK;
}
}
ELSE
{
BREAK;
}
}
}
ELSE
{
BREAK;
}
}
ELSE IF ( L_sub(L_Rcalc, L_Rcalc1 ) == 0 && sub(bwidth, SWB) != 0)
{
BREAK;
}
L_Rcalc1 = L_Rcalc;
move32();
}
return L_Rcalc;
}
+770
View File
@@ -0,0 +1,770 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "cnst_fx.h" /* Audio core constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h"
#include "stl.h"
#include "basop_mpy.h"
/*--------------------------------------------------------------------------*
* mdct_spectrum_denorm()
*
*
*--------------------------------------------------------------------------*/
void mdct_spectrum_denorm_fx(
const Word16 inp_vector[], /* i : Q0 : */
Word32 L_y2[], /* i/o : Qs : decoded spectrum */
const Word16 band_start[], /* i : Q0 : table of start freq for every subband */
const Word16 band_end[], /* i : Q0 : table of end freq for every subband */
const Word16 band_width[], /* i : Q0 : table of bandwidth for every subband */
const Word32 L_band_energy[], /* i : Qbe : band energy */
const Word16 npulses[], /* i : Q0 : number of coded spectrum */
const Word16 bands, /* i : Q0 : number of subbands */
const Word16 ld_slope_fx, /* i : Q15 : */
const Word16 pd_thresh_fx /* i : Q15 : */
)
{
Word16 i, k;
Word32 L_Eyy;
Word32 L_tmp, L_temp;
Word16 temp_fx, temp_lo_fx, temp_hi_fx;
Word32 L_inp_tmp[L_FRAME48k];
Word16 exp_norm;
Word16 exp_safe;
Word16 exp_normn, exp_normd;
Word16 pd_fx;
Word16 Qpd;
Word16 div_pd_fx;
Word16 Qdivpd;
Word32 L_div_pd;
Word16 frac, exp;
Word16 gain_tweak_fx;
Word16 Qtweak;
Word16 exp_shift;
Word16 QEyy;
Word16 pow_fx;
Word16 Qpow;
Word16 Qdiv;
Word16 Qgamma;
Word16 gamma_fx;
Word16 cond_fx;
exp_safe = 4; /* safe bit for overflow */
FOR (k = 0; k < bands; k++)
{
L_tmp = L_deposit_l(0);
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
L_inp_tmp[i] = L_mult(inp_vector[i], inp_vector[i]);
move32(); /* Q0+Q0+1 */
L_tmp = L_or(L_tmp, L_inp_tmp[i]);
}
exp_norm = norm_l(L_tmp);
exp_norm = sub(exp_norm, exp_safe);
L_Eyy = L_deposit_l(0);
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
/*Eyy += (float) inp_vector[i] * inp_vector[i]; */
L_Eyy = L_add(L_Eyy, L_shl(L_inp_tmp[i], exp_norm)); /* Q1+exp_norm */
}
QEyy = add(1, exp_norm);
IF ( L_Eyy > 0x0L )
{
/* Set gamma to be pulse gain which results in perfect quantized subband energy */
/*gamma = (float) sqrt (pow (2.0f, band_energy[k]) / Eyy); */
/* Pow part (pow(2.0f, band_energy) ) */
L_temp = L_shr(L_band_energy[k], sub(SWB_BWE_LR_Qbe, 16));
temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx);
Qpow = sub(14, temp_hi_fx);
pow_fx = extract_l(Pow2(14, temp_lo_fx)); /* Qpow */
/* Div part ( pow (2.0f, band_energy[i])/Eyy ) */
exp_normn = norm_s(pow_fx);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_l(L_Eyy);
temp_fx = div_s( shl( pow_fx, exp_normn), extract_h(L_shl(L_Eyy, exp_normd)));
Qdiv = add(sub(add(Qpow, exp_normn) , add(QEyy, exp_normd)), 31);
exp_norm = norm_s(temp_fx);
temp_fx = shl(temp_fx, exp_norm);
Qdiv = add(Qdiv, exp_norm);
/* Sqrt part sqrt(pow (2.0f, band_energy[i])/Eyy) */
Qgamma = add(Qdiv, 16);
IF ( s_and(Qdiv, 1) == 0 ) /* Qdiv % 2 == 0 */
{
L_temp = Sqrt_l(L_shr(L_deposit_h(temp_fx),1), &exp_norm);
L_temp = L_shr(L_temp, exp_norm);
Qgamma = sub(shr(Qgamma, 1), 1);
gamma_fx = round_fx(L_temp);
}
ELSE
{
L_temp = Sqrt_l(L_deposit_h(temp_fx), &exp_norm);
L_temp = L_shr(L_temp, exp_norm);
Qgamma = shr(Qgamma, 1);
gamma_fx = round_fx(L_temp);
}
/* Adjust gamma based on pulse density (0 bit MSE gain estimator) */
/*pd = (float) npulses[k] / band_width[k]; */
exp_normn = norm_s(npulses[k]);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(band_width[k]);
pd_fx = div_s(shl(npulses[k],exp_normn), shl(band_width[k], exp_normd));
Qpd = add(sub(exp_normn, exp_normd), 15);
cond_fx = sub(shl(pd_fx, sub(15, Qpd)), pd_thresh_fx/*Q15*/);
Overflow = 0;
move16(); /* allow overflow happen. */
IF ( cond_fx < 0 )
{
/*gain_tweak = (float) pow (2.0f, (ld_slope * log2_f (pd / pd_thresh))); */
/* Div part */
exp_normn = norm_s(pd_fx);
exp_normn = sub(exp_normn, 1);
exp_normd = norm_s(pd_thresh_fx);
div_pd_fx = div_s(shl(pd_fx, exp_normn), shl(pd_thresh_fx, exp_normd)); /* Qpd+exp_normn - (15 + exp_normd) + 15 */
Qdivpd = add(sub(add(Qpd, exp_normn), add(15, exp_normd)), 15);
/* Log2 part */
exp_norm = norm_s(div_pd_fx);
L_div_pd = L_deposit_h(shl(div_pd_fx, exp_norm));
Qdivpd = add(add(Qdivpd, exp_norm), 16);
frac = Log2_norm_lc(L_div_pd);
exp = sub(30, Qdivpd);
L_tmp = L_Comp(exp, frac); /* Q16 */
/* Mult part */
L_tmp = Mpy_32_16_1(L_tmp, ld_slope_fx);
/* Pow part */
temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx);
Qtweak = sub(14, temp_hi_fx);
gain_tweak_fx = extract_l(Pow2(14, temp_lo_fx));
/*gamma *= gain_tweak; */
L_tmp = L_mult(gamma_fx, gain_tweak_fx); /* Qgamma+Qtweak+1 */
exp_norm = norm_l(L_tmp);
gamma_fx = round_fx(L_shl(L_tmp, exp_norm));
Qgamma = sub(add(add(Qgamma, Qtweak), exp_norm), 15);/*Qgamma+Qtweak+1+exp_norm-16; */
}
exp_shift = sub(SWB_BWE_LR_Qs-1, Qgamma);
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
/*y2[i] = gamma * inp_vector[i]; */
L_tmp = L_mult(gamma_fx, (Word16)inp_vector[i]); /* Qgamma+0+1=Qgamma+1 */
L_y2[i] = L_shl(L_tmp, exp_shift);
move32();
}
}
}
return;
}
/*==========================================================================*/
/* FUNCTION : void hq2_core_configure_fx() */
/*--------------------------------------------------------------------------*/
/* PURPOSE : */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* Word16 *qint o: Q13 */
/* Word16 *eref o: Q10 */
/* Word16 *bit_alloc_weight o: Q13 */
/* Word16 *p2a_th o: Q11 */
/* Word16 *pd_thresh o: Q15 */
/* Word16 *ld_slope o: Q15 */
/* Word16 *ni_coef o: Q14 */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------*/
/* CALLED FROM : */
/*==========================================================================*/
void hq2_core_configure_fx (
const Word16 frame_length,
const Word16 num_bits,
const Word16 is_transient,
Word16 *bands,
Word16 *length,
Word16 band_width[],
Word16 band_start[],
Word16 band_end[],
Word32 *L_qint,
Word16 *eref,
Word16 *bit_alloc_weight,
Word16 *gqlevs,
Word16 *Ngq,
Word16 *p2a_bands,
Word16 *p2a_th,
Word16 *pd_thresh,
Word16 *ld_slope,
Word16 *ni_coef,
Word32 L_bwe_br
)
{
const Xcore_Config_fx *xcore_config_fx;
Word16 i, k;
Word16 bands_sh;
xcore_config_fx = &xcore_config_32kHz_013200bps_long_fx; /* default set for VC Warning */
IF ( sub(frame_length, L_FRAME8k) == 0 )
{
IF( is_transient )
{
IF ( sub(num_bits, ACELP_7k20 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_8kHz_007200bps_short_fx;
}
ELSE IF ( sub(num_bits, ACELP_8k00 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_8kHz_008000bps_short_fx;
}
ELSE IF ( sub(num_bits, ACELP_13k20 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_8kHz_013200bps_short_fx;
}
ELSE
{
xcore_config_fx = &xcore_config_8kHz_016400bps_short_fx;
}
}
ELSE
{
IF ( sub(num_bits, ACELP_7k20 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_8kHz_007200bps_long_fx;
}
ELSE IF ( sub(num_bits, ACELP_8k00 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_8kHz_008000bps_long_fx;
}
ELSE IF ( sub(num_bits, ACELP_13k20 / 50) <= 0)
{
xcore_config_fx = &xcore_config_8kHz_013200bps_long_fx;
}
ELSE
{
xcore_config_fx = &xcore_config_8kHz_016400bps_long_fx;
}
}
}
ELSE IF ( sub(frame_length, L_FRAME16k) == 0 )
{
IF (is_transient)
{
IF ( sub(num_bits, ACELP_13k20 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_16kHz_013200bps_short_fx;
move16();
}
ELSE if ( sub(num_bits, ACELP_16k40 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_16kHz_016400bps_short_fx;
move16();
}
}
ELSE
{
IF ( sub(num_bits, ACELP_13k20 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_16kHz_013200bps_long_fx;
move16();
}
ELSE if ( sub(num_bits, ACELP_16k40 / 50) <= 0 )
{
xcore_config_fx = &xcore_config_16kHz_016400bps_long_fx;
move16();
}
}
}
ELSE /* (frame_length == SWB) */
{
IF (is_transient)
{
IF ( L_sub(L_bwe_br, ACELP_13k20) <= 0 )
{
xcore_config_fx = &xcore_config_32kHz_013200bps_short_fx;
move16();
}
ELSE if ( L_sub(L_bwe_br, ACELP_16k40) <= 0 )
{
xcore_config_fx = &xcore_config_32kHz_016400bps_short_fx;
move16();
}
}
ELSE
{
IF ( L_sub(L_bwe_br, ACELP_13k20) <= 0 )
{
xcore_config_fx = &xcore_config_32kHz_013200bps_long_fx;
move16();
}
ELSE if ( L_sub(L_bwe_br, ACELP_16k40) <= 0 )
{
xcore_config_fx = &xcore_config_32kHz_016400bps_long_fx;
move16();
}
}
}
*bands = xcore_config_fx->bands;
move16();
*length = xcore_config_fx->bw;
move16();
*L_qint = xcore_config_fx->L_qint;
move32();
*eref = xcore_config_fx->eref;
move16();
*bit_alloc_weight = xcore_config_fx->bit_alloc_weight;
move16();
*gqlevs = xcore_config_fx->gqlevs;
move16();
*Ngq = xcore_config_fx->Ngq;
move16();
*p2a_bands = xcore_config_fx->p2a_bands;
move16();
*p2a_th = xcore_config_fx->p2a_th;
move16();
*pd_thresh = xcore_config_fx->pd_thresh;
move16();
*ld_slope = xcore_config_fx->ld_slope;
move16();
*ni_coef = xcore_config_fx->ni_coef;
move16();
/*mvs2s_fx (xcore_config_fx->band_width, band_width, *bands); */
Copy(xcore_config_fx->band_width, band_width, *bands);
/* Expand band_width[] table for short windows */
IF (is_transient)
{
bands_sh = *bands;
move16();
*bands = shl(bands_sh,2);
*length = shl(*length, 2);
FOR (i = 1; i <= 3; i++)
{
FOR (k = 0; k < bands_sh; k++)
{
band_width[i * bands_sh + k] = band_width[k];
move16();
}
}
}
/* Formulate band_start and band_end tables from band_width table */
band_start[0] = 0;
move16();
band_end[0] = sub(band_width[0], 1);
move16();
FOR (k = 1; k < *bands; k++)
{
band_start[k] = add( band_start[k - 1] , band_width[k - 1]);
move16();
band_end[k] = sub(add( band_start[k] , band_width[k]) , 1);
move16();
}
return;
}
/*--------------------------------------------------------------------------*
* reverse_transient_frame_energies()
*
*
*--------------------------------------------------------------------------*/
void reverse_transient_frame_energies_fx(
Word32 L_band_energy[], /* o : Q14 : band energies */
const Word16 bands /* i : Q0 : number of bands */
)
{
Word16 k, k1, k2;
Word32 L_be;
Word16 bands_2, bands_4, bands_8;
Word32 *p_be1, *p_be2;
bands_2 = shr(bands, 1);
bands_4 = shr(bands, 2);
bands_8 = shr(bands, 3);
k1 = bands_4;
k2 = sub(bands_2, 1);
p_be1 = &L_band_energy[k1];
p_be2 = &L_band_energy[k2];
FOR( k = 0; k < bands_8; k++ )
{
L_be = *p_be1;
move32();
*p_be1 = *p_be2;
move32();
*p_be2 = L_be;
move32();
p_be1++;
p_be2--;
}
k1 = sub(bands, bands_4); /* 3*bands/4 */
k2 = sub(bands, 1);
p_be1 = &L_band_energy[k1];
p_be2 = &L_band_energy[k2];
FOR( k = 0; k < bands_8; k++ )
{
L_be = *p_be1;
move32();
*p_be1 = *p_be2;
move32();
*p_be2 = L_be;
move32();
p_be1++;
p_be2--;
}
return;
}
/*--------------------------------------------------------------------------*
* spt_shorten_domain_pre()
*
* Compute shorten subband if previous frame has spectral peak.
*--------------------------------------------------------------------------*/
void spt_shorten_domain_pre_fx(
const Word16 band_start[], /* i: Starting position of sub band */
const Word16 band_end[], /* i: End position of sub band */
const Word16 prev_SWB_peak_pos[], /* i: Spectral peak */
const Word16 BANDS, /* i: total number of bands */
const Word32 L_bwe_br, /* i: bitrate information */
Word16 new_band_start[], /* o: Starting position of new shorten sub band */
Word16 new_band_end[], /* o: End position of new shorten sub band */
Word16 new_band_width[] /* o: new sub band bandwidth */
)
{
Word16 j;
Word16 k;
Word16 kpos;
Word16 new_band_width_half;
const Word16 *p_bw_SPT_tbl; /* pointer of bw_SPT_tbl */
p_bw_SPT_tbl = bw_SPT_tbl[0];
if( L_sub(L_bwe_br, HQ_16k40) == 0 )
{
p_bw_SPT_tbl = bw_SPT_tbl[1];
}
kpos = 0;
j = 0;
move16();
FOR(k=sub(BANDS,SPT_SHORTEN_SBNUM); k<BANDS; k++)
{
IF ( prev_SWB_peak_pos[kpos] != 0)
{
new_band_width[j] = p_bw_SPT_tbl[j];
/*shorten the bandwidth for pulse resolution*/
new_band_width_half = shr(new_band_width[j], 1);
move16();
new_band_start[j] = sub(prev_SWB_peak_pos[kpos], new_band_width_half);
move16();
new_band_end[j] = add(prev_SWB_peak_pos[kpos], new_band_width_half);
move16();
IF( sub(new_band_start[j], band_start[k]) < 0 )
{
new_band_start[j] = band_start[k];
move16();
new_band_end[j] = add(new_band_start[j], sub(new_band_width[j],1));
move16();
}
ELSE IF ( sub(new_band_end[j], band_end[k]) > 0 )
{
new_band_end[j] = band_end[k];
move16();
new_band_start[j] = sub(new_band_end[j], sub(new_band_width[j],1));
move16();
}
}
ELSE
{
new_band_width[j] = p_bw_SPT_tbl[j];
/*shorten the bandwidth for pulse resolution*/
new_band_width_half = shr(new_band_width[j], 1);
move16();
new_band_start[j] = sub(shr(add(band_start[k], band_end[k]), 1), new_band_width_half);
move16();
new_band_end[j] = add(shr(add(band_start[k], band_end[k]), 1), new_band_width_half);
move16();
}
kpos = add(kpos, 1);
j = add(j, 1);
}
return;
}
/*--------------------------------------------------------------------------*
* spt_shorten_domain_band_save()
*
* Store the original subband information
*--------------------------------------------------------------------------*/
void spt_shorten_domain_band_save_fx(
const Word16 bands, /* i: total subband */
const Word16 band_start[], /* i: starting position of subband */
const Word16 band_end[], /* i: end position of subband */
const Word16 band_width[], /* i: band width of subband */
Word16 org_band_start[], /* o: starting position of subband */
Word16 org_band_end[], /* o: end position of subband */
Word16 org_band_width[] /* o: band width of subband */
)
{
Word16 k;
Word16 kpos;
kpos = 0;
move16();
FOR(k=sub(bands,SPT_SHORTEN_SBNUM); k<bands; k++)
{
org_band_start[kpos] = band_start[k];
move16();
org_band_end[kpos] = band_end[k];
move16();
org_band_width[kpos] = band_width[k];
move16();
kpos = add(kpos, 1);
}
return;
}
/*--------------------------------------------------------------------------*
* spt_shorten_domain_band_restore()
*
* Restrore the subband information
*--------------------------------------------------------------------------*/
void spt_shorten_domain_band_restore_fx(
const Word16 bands, /* i: total subband */
Word16 band_start[], /* i/o: starting position of subband */
Word16 band_end[], /* i/o: end position of subband */
Word16 band_width[], /* i/o: band width of subband */
const Word16 org_band_start[], /* o: starting position of subband */
const Word16 org_band_end[], /* o: end position of subband */
const Word16 org_band_width[] /* o: band width of subband */
)
{
Word16 k;
Word16 kpos;
kpos = 0;
move16();
FOR(k=sub(bands,SPT_SHORTEN_SBNUM); k<bands; k++)
{
band_start[k] = org_band_start[kpos];
move16();
band_end[k] = org_band_end[kpos];
move16();
band_width[k] = org_band_width[kpos];
move16();
kpos = add(kpos, 1);
}
return;
}
/*--------------------------------------------------------------------------*
* spt_swb_peakpos_tmp_save
*
* Save Peak position for every higher subband
*--------------------------------------------------------------------------*/
void spt_swb_peakpos_tmp_save_fx(
const Word32 L_y2[], /* i: coded spectral information */
const Word16 bands, /* i: total number of bands */
const Word16 band_start[], /* i: starting position of subband */
const Word16 band_end[], /* i: end position of subband */
Word16 prev_SWB_peak_pos_tmp[] /* o: spectral peaks */
)
{
Word16 i, j, k;
Word32 L_peak_max;
Word32 L_abs_y2;
j = 0;
move16();
FOR(k=sub(bands, SPT_SHORTEN_SBNUM); k<bands; k++)
{
L_peak_max = L_deposit_l(0);
prev_SWB_peak_pos_tmp[j] = 0;
move16();
FOR(i=band_start[k]; i<=band_end[k]; i++)
{
L_abs_y2 = L_abs(L_y2[i]);
move32();
IF( L_sub( L_peak_max, L_abs_y2) < 0x0L )
{
L_peak_max = L_abs_y2;
move32();
prev_SWB_peak_pos_tmp[j] = i;
move16();
}
}
j = add(j, 1);
}
return;
}
void bit_allocation_second_fx(
Word32 *Rk,
Word32 *Rk_sort,
Word16 BANDS,
const Word16 *band_width,
Word16 *k_sort,
Word16 *k_num,
const Word16 *p2a_flags,
const Word16 p2a_bands,
const Word16 *last_bitalloc,
const Word16 input_frame
)
{
Word16 k, k2 = 0;
Word16 ever_bits[BANDS_MAX], ever_sort[BANDS_MAX];/*Q12 */
Word16 class_flag = 0;
Word16 rk_temp = 32767, ever_temp = 32767;/*Q12 */
Word16 exp;
Word16 tmp;
Word32 L_tmp;
FOR (k = 0; k < BANDS; k++)
{
test();
test();
test();
IF((( sub(k_sort[k],sub(BANDS,p2a_bands)) >= 0 )&&( sub(p2a_flags[k_sort[k]],1) == 0 )) ||
(( sub(k_sort[k],sub(BANDS,2)) >= 0 )&&( sub(last_bitalloc[sub(k_sort[k], sub(BANDS,2))], 1) == 0 )))
{
exp = norm_s(band_width[k_sort[k]]);
tmp = shl(band_width[k_sort[k]],exp);/*Q(exp) */
tmp = div_s(16384,tmp);/*Q(15+14-exp = 29-exp) */
L_tmp = Mult_32_16(Rk_sort[k],tmp);/* Q(16+29-exp-15 = 30-exp) */
tmp = sub(18,exp);
ever_bits[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */
IF( sub(ever_bits[k],rk_temp) < 0 )
{
rk_temp = ever_bits[k];
move16();
k2 = k;
move16();
}
class_flag = 1;
}
}
test();
IF( class_flag ==0 || sub(input_frame,L_FRAME8k) == 0)
{
FOR(k = 0; k < BANDS; k++)
{
test();
IF( sub(k_sort[k],sub(BANDS,p2a_bands)) < 0 && Rk_sort[k] > 0 )
{
exp = norm_s(band_width[k_sort[k]]);
tmp = shl(band_width[k_sort[k]],exp);/*Q(exp) */
tmp = div_s(16384,tmp);/*Q(15+14-exp = 29-exp) */
L_tmp = Mult_32_16(Rk_sort[k],tmp);/* Q(16+29-exp-15 = 30-exp) */
tmp = sub(18,exp);
ever_sort[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */
IF(sub(ever_sort[k],ever_temp) < 0)
{
ever_temp = ever_sort[k];
move16();
k2 = k;
move16();
}
}
}
}
k_num[0] = k2;
IF(sub(k_sort[k2],sub(BANDS,1)) == 0)
{
FOR (k = 0; k < BANDS; k++)
{
if(sub(k_sort[k],sub(k_sort[k2],1)) == 0)
{
k_num[1] = k;
move16();
}
}
}
ELSE IF(k_sort[k2] == 0)
{
FOR (k = 0; k < BANDS; k++)
{
if(sub(k_sort[k],add(k_sort[k2],1)) == 0)
{
k_num[1] = k;
move16();
}
}
}
ELSE
{
IF ( L_sub( Rk[sub(k_sort[k2],1)],Rk[add(k_sort[k2],1)] ) < 0 )
{
FOR (k = 0; k < BANDS; k++)
{
if(sub(k_sort[k],sub(k_sort[k2],1)) == 0)
{
k_num[1] = k;
move16();
}
}
}
ELSE
{
FOR (k = 0; k < BANDS; k++)
{
if(sub(k_sort[k],add(k_sort[k2],1)) == 0)
{
k_num[1] = k;
move16();
}
}
}
}
}
+615
View File
@@ -0,0 +1,615 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "stl.h"
#include "prot_fx.h"
#include "math_op.h"
#include "math_32.h"
#include "oper_32b.h"
#include "move.h"
#include "count.h"
/*--------------------------------------------------------------------------*
* hq2_noise_inject()
*
* HQ2 noise injection for WB signals
*--------------------------------------------------------------------------*/
void hq2_noise_inject_fx(
Word32 L_y2[],
const Word16 band_start[],
const Word16 band_end[],
const Word16 band_width[],
Word32 Ep_fx[],
Word32 Rk_fx[],
const Word16 npulses[],
Word16 ni_seed,
const Word16 bands,
const Word16 ni_start_band,
const Word16 bw_low,
const Word16 bw_high,
const Word32 enerL_fx,
const Word32 enerH_fx,
Word32 last_ni_gain_fx[],
Word16 last_env_fx[],
Word16 *last_max_pos_pulse,
Word16 *p2a_flags,
Word16 p2a_bands,
const Word16 hqswb_clas,
const Word16 bwidth,
const Word32 bwe_br
)
{
Word32 L_tmp,L_tmp2,L_tmp2x,L_tmp3,L_tmp1;
Word16 exp,exp2,Q_speech;
Word16 pd_fx[BANDS_MAX], rand_fx, peak_fx[BANDS_MAX], fac_fx;
Word16 tmp,tmpx,tmp1,tmp2,tmp3,tmp4,Q_env_fx[BANDS_MAX],Q_Ep_fx[BANDS_MAX];
Word16 Qs=SWB_BWE_LR_Qs;
Word32 env_fx[BANDS_MAX];
Word16 env_fx2[BANDS_MAX];
Word32 ni_gain_fx[BANDS_MAX];
Word16 y2hat_fx[L_FRAME48k];
Word16 i, j, k, ni_end_band, satur, count[BANDS_MAX], max_pos_pulse, pos;
Word16 sb = bands;
satur = 0;
move16();
FOR(i = 0 ; i < bands; i++)
{
Ep_fx[i] = L_shl(Ep_fx[i], 6);/* Q-6 -> Q0 */ move32();
}
tmp = add(band_end[bands-1], 1);
FOR (k = 0; k < tmp; k++)
{
y2hat_fx[k] = (Word16)L_min(L_max(L_shr(L_y2[k],Qs),-32768),32767);
move16(); /* Extract_l or something else is missing here */
}
test();
test();
test();
test();
IF( (sub(hqswb_clas,HQ_HARMONIC) ==0 || sub(hqswb_clas,HQ_NORMAL) ==0 ) && (L_sub(bwe_br,HQ_16k40) ==0 || L_sub(bwe_br,HQ_13k20) ==0 ) && sub(bwidth,SWB) ==0 )
{
sb = 17;
move16();
if( L_sub(bwe_br,HQ_16k40) == 0 )
{
sb = 19;
move16();
}
}
/* calculate the envelopes/ the decoded peak coeff./number of the decoded coeff./ the last subbands of the bit-allocated/saturation of bit-allocation */
ni_end_band = bands;
max_pos_pulse = bands;
FOR (k = ni_start_band; k < ni_end_band; k++)
{
tmp = div_s(1, band_width[k]); /*Q15 */
L_tmp = Mult_32_16(Rk_fx[k],tmp);/*Q(16+15-15=16) */
pd_fx[k] = extract_h(L_shl(L_tmp,10)); /*16+10-16 =Q10 */
L_tmp2 = L_add(0,Ep_fx[k]);/*Q0 */
L_tmp = L_max(1, L_tmp2);
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
L_tmp3 = L_add(0,(Word32)band_width[k]);
exp2 = norm_l(L_tmp3);
tmp2 = extract_h(L_shl(L_tmp3, exp2));
exp2 = sub(exp, exp2); /* Denormalize and substract */
tmp3 = sub(tmp2, tmp);
if (tmp3 > 0)
{
tmp2 = shr(tmp2, 1);
}
if (tmp3 > 0)
{
exp2 = add(exp2, 1);
}
tmp = div_s(tmp2, tmp);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp2);
env_fx[k] = L_tmp;
move32();/*Q(31-exp2) move32(); */
Q_env_fx[k] = sub(31,exp2);
move16();
tmp = sub(17,Q_env_fx[k]);
env_fx2[k] = extract_h(L_shl(env_fx[k],tmp));/*Q1 */
peak_fx[k] = 0;
move16();
count[k] = 0;
move16();
IF(npulses[k] != 0)
{
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
L_tmp =L_mult0(y2hat_fx[i],y2hat_fx[i]); /*0 */
Ep_fx[k] =L_sub(Ep_fx[k],L_tmp);
move32();/*0 */
IF(sub(abs_s(y2hat_fx[i]),peak_fx[k]) > 0)
{
peak_fx[k] = abs_s(y2hat_fx[i]);
move16();/*0 */
}
IF(y2hat_fx[i] != 0)
{
count[k] = add(count[k],1);
move16();
}
}
max_pos_pulse = k;
L_tmp2 = L_add(0,Ep_fx[k]);
L_tmp = L_max(1, L_tmp2);
exp = norm_l(L_tmp);
tmp = extract_h(L_shl(L_tmp, exp));
L_tmp3 = (Word32)band_width[k];
exp2 = norm_l(L_tmp3);
tmp2 = extract_h(L_shl(L_tmp3, exp2));
exp2 = sub(exp, exp2); /* Denormalize and substract */
tmp3 = sub(tmp2, tmp);
if (tmp3 > 0)
{
tmp2 = shr(tmp2, 1);
}
if (tmp3 > 0)
{
exp2 = add(exp2, 1);
}
tmp = div_s(tmp2, tmp);
L_tmp = L_deposit_h(tmp);
L_tmp = Isqrt_lc(L_tmp, &exp2);
Ep_fx[k] = L_tmp;
move32();/*Q(31-exp2) */
Q_Ep_fx[k] = sub(31,exp2);
move16();
}
ELSE
{
Ep_fx[k] = env_fx[k];
move32();/*Q(Q_env_fx[k]) */
Q_Ep_fx[k] = Q_env_fx[k];
move16();/*31-exp2 */
}
}
FOR(k = ni_start_band; k < ni_end_band; k++)
{
/* calculate the noise gain */
satur =0;
move16();
if(sub(pd_fx[k],819)>= 0)
{
satur =1;
move16();
}
test();
IF (satur == 0 && Ep_fx[k] > 0)
{
IF(npulses[k] != 0)
{
IF( sub(bwidth,SWB) ==0)
{
IF(sub(hqswb_clas,HQ_TRANSIENT) !=0 )
{
IF(peak_fx[k]!=0)
{
Q_speech = norm_s(peak_fx[k]);
tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */
}
ELSE
{
tmp = 0x7fff;
move16();
Q_speech = 0;
move16();
}
L_tmp2x = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15 = Q_Ep_fx[k]-Q_speech+14) */
tmp = sub(Q_Ep_fx[k],Q_speech);
tmpx = add(tmp,1);
tmp2 = extract_l(L_shr(L_tmp2x,s_min(tmpx, 31)));/*Q13 Ep[k]/peak[k] */
IF(sub(hqswb_clas,HQ_HARMONIC) == 0 )
{
tmp = sub(1536,pd_fx[k]); /*Q10 */
tmp3 = shl(tmp,4); /*Q14 */
L_tmp = Mult_32_16(env_fx[k],tmp3);/*Q(Q_env_fx[k]+14-15 = Q_env_fx[k]-1) */
L_tmp = Mult_32_16(L_tmp,6144);/*Q(Q_env_fx[k]-1+10-15 = Q_env_fx[k]-6) */
IF(peak_fx[k]!=0)
{
Q_speech = norm_s(peak_fx[k]);
tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */
}
ELSE
{
tmp = 0x7fff;
move16();
Q_speech = 0;
move16();
}
L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15=Q_Ep_fx[k]-Q_speech+14) */
L_tmp3 = Mult_32_16(L_tmp,tmp);/* Q(Q_env_fx[k]-6+29-Q_speech-15=Q_env_fx[k]-Q_speech+8) */
L_tmp = Mult_32_32(L_tmp2,L_tmp3); /*Q(Q_Ep_fx[k]-Q_speech+14+Q_env_fx[k]-Q_speech+8-31=Q_Ep_fx[k]+Q_env_fx[k]-2*Q_speech-9) */
tmp = add(Q_Ep_fx[k],Q_env_fx[k]);
tmp = sub(tmp,Q_speech);
tmp = sub(tmp,Q_speech);
tmp = sub(37,tmp);
tmp1= extract_h(L_shl(L_tmp,tmp));/*Q12 //6.0f*(1.5f - pd[k])*env[k]*Ep[k]/(peak[k]*peak[k]) */
fac_fx = tmp1;
move16();/*Q12 */
if(sub(k,sb) > 0)
{
fac_fx =mult(24576,tmp2);/*//Q(14+13-15=12) */
}
}
ELSE
{
IF(sub(k,sb) <= 0)
{
tmp = sub(1536,pd_fx[k]); /*Q10 */
tmp3 = shl(tmp,4); /*Q14 */
L_tmp = Mult_32_16(L_tmp2x,tmp3);/*Q(Q_Ep_fx[k]-Q_speech+14+14-15 = Q_Ep_fx[k]-Q_speech+13) */
L_tmp = Mult_32_16(L_tmp,20480);/*Q(Q_Ep_fx[k]-Q_speech+13+12-15 = Q_Ep_fx[k]-Q_speech+10) */
fac_fx= extract_h(L_shl(L_tmp,sub(add(18,Q_speech),Q_Ep_fx[k])));/*Q_Ep_fx[k]-Q_speech+10 +18+Q_speech-Q_Ep_fx[k] -16 =12 */
}
ELSE
{
fac_fx =shl(mult(32767,tmp2),1);/*//Q(13+13-15+1=12) */
}
}
}
ELSE
{
fac_fx = 4505;
move16();/*Q12 */
}
}
ELSE
{
tmp = sub(1536,pd_fx[k]); /*Q10 */
tmp2 = s_min(1024,tmp); /*q10 */
tmp2 = shl(tmp2,4); /*Q14 */
L_tmp = Mult_32_16(env_fx[k],tmp2);/*Q(Q_env_fx[k]+14-15 = Q_env_fx[k]-1) */
L_tmp = Mult_32_16(L_tmp,20480);/*Q(Q_env_fx[k]-1+10-15 = Q_env_fx[k]-6) */
IF(peak_fx[k]!=0)
{
Q_speech = norm_s(peak_fx[k]);
tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */
}
ELSE
{
tmp = 0x7fff;
move16();
Q_speech = 0;
move16();
}
L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15=Q_Ep_fx[k]-Q_speech+14) */
L_tmp3 = Mult_32_16(L_tmp,tmp);/* Q(Q_env_fx[k]-6+29-Q_speech-15=Q_env_fx[k]-Q_speech+8) */
L_tmp = Mult_32_32(L_tmp2,L_tmp3); /*Q(Q_Ep_fx[k]-Q_speech+14+Q_env_fx[k]-Q_speech+8-31=Q_Ep_fx[k]+Q_env_fx[k]-2*Q_speech-9) */
tmp = add(Q_Ep_fx[k],Q_env_fx[k]);
tmp = sub(tmp,Q_speech);
tmp = sub(tmp,Q_speech);
tmp = sub(37,tmp);
fac_fx = extract_h(L_shl(L_tmp,tmp));/*Q12 */
test();
IF(sub(k,1) > 0 && sub(k,sub(ni_end_band,1)) < 0)
{
IF(env_fx2[k]!=0)
{
Q_speech = norm_s(env_fx2[k]);
tmp = shl(env_fx2[k],Q_speech);/*Q(Q_speech+1) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech-1=28-Q_speech) */
Q_speech = sub(28,Q_speech);
}
ELSE
{
tmp =0x7fff;
move16();
Q_speech = 0;
move16();
}
tmp1 = mult(env_fx2[add(k,1)],16384);/*Q(1+15-15=1) Q1 */
tmp2 = sub(env_fx2[k],tmp1);
tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */
tmp3 = sub(tmp1,env_fx2[sub(k,1)]);
tmp1 = mult(peak_fx[k],16384);/*Q(0+15-15=0) Q0 */
tmp4 = sub(tmp1,shr(env_fx2[k],1));
test();
test();
test();
IF(count[add(k,1)] == 0 && tmp2 > 0 && tmp3 < 0)
{
L_tmp = L_mult(env_fx2[add(k,1)],tmp);/* Q(1+Q_speech+1 = Q_speech+2) */
L_tmp = Mult_32_16(L_tmp,24576); /*Q(Q_speech+2+14-15=Q_speech+1) */
fac_fx = extract_h(L_shl(L_tmp,sub(27,Q_speech)));/*Q12 */
}
ELSE IF(count[sub(k,1)] == 0 && tmp4 > 0)
{
L_tmp = L_mult(env_fx2[sub(k,1)],tmp); /* Q(1+Q_speech+1 = Q_speech+2) */
fac_fx = extract_h(L_shl(L_tmp,sub(26,Q_speech)));/*Q12 */
}
}
test();
IF(sub(k,sub(ni_end_band,p2a_bands)) >= 0 && sub(bwidth, WB) == 0)
{
L_tmp = Mult_32_16(enerH_fx, bw_low);
L_tmp2= Mult_32_16(enerL_fx, bw_high);
L_tmp = L_sub(L_tmp,L_tmp2);
tmp1 = mult(peak_fx[k],16384);/*Q(0+15-15=0) Q0 */
tmp4 = sub(tmp1,shr(env_fx2[k],1));
test();
IF(L_tmp > 0 && tmp4 < 0)
{
IF(peak_fx[k]!=0)
{
Q_speech = norm_s(peak_fx[k]);
tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */
}
ELSE
{
tmp = 0x7fff;
move16();
Q_speech = 0;
move16();
}
L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15 = Q_Ep_fx[k]-Q_speech+14) */
tmp = sub(Q_Ep_fx[k],Q_speech);
tmp = add(tmp,1);
tmp = extract_l(L_shr(L_tmp2,tmp));/*Q13 */
tmp = sub(16384,tmp);/*Q13 */
fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),2));/*Q12*/
}
IF(p2a_flags[k] == 0)
{
L_tmp2 = Mult_32_16(Ep_fx[k],fac_fx);/*Q(Q_Ep_fx[k]+12-15 = Q_Ep_fx[k]-3) */
Q_speech = norm_l(L_tmp2);
tmp = extract_h(L_shl(L_tmp2,Q_speech));/*Q(Q_Ep_fx[k]-3+Q_speech-16 = Q_Ep_fx[k]+Q_speech-19) */
IF(tmp != 0)
{
tmp = div_s(16384,tmp);/*Q(15+14-Q_Ep_fx[k]-Q_speech+19 = 48-Q_Ep_fx[k]-Q_speech) */
L_tmp2 = Mult_32_16(env_fx[k],tmp);/*Q(Q_env_fx[k]+48-Q_Ep_fx[k]-Q_speech-15 = Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+33) */
L_tmp2 = Mult_32_16(L_tmp2,20480);/*Q(Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+33+14-15 = Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+32) */
tmp = sub(Q_env_fx[k],Q_Ep_fx[k]);
tmp = sub(tmp,Q_speech);
tmp = add(tmp,25);
L_tmp = L_shr(L_tmp2,tmp);/*Q7 */
tmp = extract_l(L_min(L_tmp,192));/* */
fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),8));/*Q12 */
}
ELSE
{
tmp = 0x7fff;/*Q0 */
L_tmp2 = Mult_32_16(env_fx[k],tmp);/*Q(Q_env_fx[k]+0-15 = Q_env_fx[k]-15) */
L_tmp2 = Mult_32_16(L_tmp2,20480);/*Q(Q_env_fx[k]-15+14-15 = Q_env_fx[k]-16) */
tmp = sub(Q_env_fx[k],23);
L_tmp = L_shr(L_tmp2,tmp);/*Q7 */
tmp = extract_l((L_min(L_tmp,192)));/* */
fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),8));/*Q12 */
}
}
}
}
}
ELSE
{
fac_fx = 4505;
move16();
test();
if( sub(hqswb_clas,HQ_HARMONIC) == 0 && sub(bwidth,SWB) == 0 )
{
fac_fx = 3277;
move16();
}
}
L_tmp = Mult_32_16(Ep_fx[k],fac_fx);/*Q(Q_Ep_fx[k]+12-15 = Q_Ep_fx[k]-3) */
ni_gain_fx[k] = L_shr(L_tmp,sub(Q_Ep_fx[k],20));
move32();/*Q17 */
}
ELSE
{
ni_gain_fx[k] = L_deposit_l(0);
}
/* smooth the noise gain between the current frame and the previous frame */
pos = s_max(max_pos_pulse, *last_max_pos_pulse);
move16();
if( sub(bwidth,SWB) == 0 )
{
pos = sub(ni_end_band,1);
move16();
}
IF(sub(k,pos) <=0 )
{
test();
IF(k > 0 && add(sub(k,ni_end_band),1) < 0)
{
tmp1 = mult(last_env_fx[k],16384);/*Q(1+15-15=1) Q1 */
tmp2 = sub(env_fx2[k],tmp1);/*>0 */
tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */
tmp3 = sub(tmp1,last_env_fx[k]);/*<0 */
L_tmp = L_add((Word32)env_fx2[k],(Word32)env_fx2[sub(k,1)]);
L_tmp = L_add(L_tmp,(Word32)env_fx2[add(k,1)]);/*Q1 */
L_tmp1 = L_add((Word32)last_env_fx[k],(Word32)last_env_fx[sub(k,1)]);
L_tmp1 = L_add(L_tmp1,(Word32)last_env_fx[add(k,1)]);/*Q1 */
L_tmp2 = Mult_32_16(L_tmp1,16384);/*Q(1+15-15) Q1 */
L_tmp2 = L_sub(L_tmp,L_tmp2);/*>0 */
L_tmp3 = Mult_32_16(L_tmp,16384);/*Q(1+15-15) Q1 */
L_tmp3 = L_sub(L_tmp3,L_tmp1);/*<0 */
test();
test();
test();
IF( (tmp2 > 0 && tmp3 < 0) ||(L_tmp2 > 0 && L_tmp3 < 0))
{
IF( L_sub(ni_gain_fx[k],last_ni_gain_fx[k]) > 0 )
{
L_tmp = Mult_32_16(ni_gain_fx[k],6554);/*Q(17+15-15 = 17) */
L_tmp1 = Mult_32_16(last_ni_gain_fx[k],26214);/*Q17 */
ni_gain_fx[k] = L_add(L_tmp,L_tmp1);
move32();
}
ELSE
{
L_tmp = Mult_32_16(ni_gain_fx[k],19661);/*Q(17+15-15 = 17) */
L_tmp1 = Mult_32_16(last_ni_gain_fx[k],13107);/*Q17 */
ni_gain_fx[k] = L_add(L_tmp,L_tmp1);
move32();
}
}
}
ELSE IF (add(sub(k,ni_end_band),1) == 0)
{
tmp1 = mult(last_env_fx[k],16384);/*Q(1+15-15=1) Q1 */
tmp2 = sub(env_fx2[k],tmp1);/*>0 */
tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */
tmp3 = sub(tmp1,last_env_fx[k]);/*<0 */
L_tmp = L_add((Word32)env_fx2[k],(Word32)env_fx2[sub(k,1)]);/*Q1 */
L_tmp1 = L_add((Word32)last_env_fx[k],(Word32)last_env_fx[sub(k,1)]);/*Q1 */
L_tmp2 = Mult_32_16(L_tmp1,16384);/*Q(1+15-15) Q1 */
L_tmp2 = L_sub(L_tmp,L_tmp2);/*>0 */
L_tmp3 = Mult_32_16(L_tmp,16384);/*Q(1+15-15) Q1 */
L_tmp3 = L_sub(L_tmp3,L_tmp1);/*<0 */
test();
test();
test();
IF( (tmp2 > 0 && tmp3 < 0) ||(L_tmp2 > 0 && L_tmp3 < 0))
{
IF( L_sub(ni_gain_fx[k],last_ni_gain_fx[k]) > 0 )
{
L_tmp = Mult_32_16(ni_gain_fx[k],6554);/*Q(17+15-15 = 17) */
L_tmp1 = Mult_32_16(last_ni_gain_fx[k],26214);/*Q17 */
ni_gain_fx[k] = L_add(L_tmp,L_tmp1);
move32();
}
ELSE
{
L_tmp = Mult_32_16(ni_gain_fx[k],19661);/*Q(17+15-15 = 17) */
L_tmp1 = Mult_32_16(last_ni_gain_fx[k],13107);/*Q17 */
ni_gain_fx[k] = L_add(L_tmp,L_tmp1);
move32();
}
}
}
}
/* inject noise into the non-decoded coeffs */
test();
test();
IF(add(sub(k,ni_end_band),p2a_bands) >=0 && p2a_flags[k] == 0 && sub(bwidth,SWB) !=0 )
{
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
IF (L_y2[i] != 0)
{
L_y2[i] = Mult_32_16(L_y2[i],26215);
move32();/*Q(12+15-15=12) */
}
}
}
test();
test();
test();
IF(sub(k,max_pos_pulse) == 0 && add(sub(k,bands),p2a_bands)< 0 && sub(satur,1) != 0 && sub(bwidth,SWB) !=0)
{
j = 0;
Q_speech = norm_l(ni_gain_fx[k]);
tmp = extract_h(L_shl(ni_gain_fx[k],Q_speech));/*Q(Q_speech+1) */
IF(tmp != 0)
{
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech-1 = 28-Q_speech) */
L_tmp = Mult_32_16(Ep_fx[k],tmp); /*Q(Q_Ep_fx[k]+28-Q_speech-15 = Q_Ep_fx[k]+13-Q_speech) */
tmp = sub(Q_Ep_fx[k],Q_speech);
tmp = sub(15,tmp);
tmp = extract_h(L_shl(L_tmp,tmp));/*Q12 */
}
ELSE
{
tmp = 0x7fff;/*Q0 */
L_tmp = Mult_32_16(Ep_fx[k],tmp); /*Q(Q_Ep_fx[k]+0-15 = Q_Ep_fx[k]-15) */
tmp = sub(43,Q_Ep_fx[k]);
tmp = extract_h(L_shl(L_tmp,tmp));/*Q12 */
}
fac_fx = s_max(tmp,4096);/*Q12 */
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
IF (L_y2[i] == 0)
{
rand_fx = Random(&ni_seed); /*Q15 */
IF(band_width[k] != 0)
{
Q_speech = norm_s(band_width[k]);
tmp = shl(band_width[k],Q_speech);/*Q(Q_speech) */
tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */
}
ELSE
{
tmp = 0x7fff;
Q_speech = 0;
}
tmp1 = sub(fac_fx,4096);/*Q12 */
L_tmp = L_mult(tmp1,j);/*Q13 */
L_tmp = Mult_32_16(L_tmp,tmp);/*Q(13+29-Q_speech-15 = 27-Q_speech) */
tmp = extract_h(L_shl(L_tmp,add(1,Q_speech)));/*Q12 */
tmp = sub(fac_fx,tmp);/*Q12 */
L_tmp = Mult_32_16(ni_gain_fx[k],tmp);/*Q(17+12-15=14) */
L_y2[i] = L_add(L_y2[i],L_shr(Mult_32_16(L_tmp,rand_fx),2));
move32();/*Q12 */
}
j=add(j,1);
}
}
ELSE
{
FOR (i = band_start[k]; i <= band_end[k]; i++)
{
IF (L_y2[i] == 0)
{
rand_fx = Random(&ni_seed); /*Q15 */
L_tmp = Mult_32_16(ni_gain_fx[k],rand_fx);/*Q(17+15-15=17) */
L_y2[i] = L_add(L_y2[i],L_shr(L_tmp,5));
move32();/*Q12 */
}
}
}
}
Copy(env_fx2,last_env_fx,ni_end_band);
Copy32(ni_gain_fx,last_ni_gain_fx,ni_end_band);
*last_max_pos_pulse = max_pos_pulse;
move16();
return;
}
+217
View File
@@ -0,0 +1,217 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h" /* required for wmc_tool */
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Common constants */
/*--------------------------------------------------------------------------*
* hq_bit_allocation_fx()
*
* Assign bits for HQ fine structure coding with PVQ
*--------------------------------------------------------------------------*/
void hq_bit_allocation_fx(
const Word32 core_brate, /* i : Core bit-rate Q0 */
const Word16 length, /* i : Frame length Q0 */
const Word16 hqswb_clas, /* i : HQ class Q0 */
Word16 *num_bits, /* i/o: Remaining bit budget Q0 */
const Word16 *normqlg2, /* i : Quantized norms Q0 */
const Word16 nb_sfm, /* i : Number sub bands to be encoded Q0 */
const Word16 *sfmsize, /* i : Sub band bandwidths Q0 */
Word16 *noise_level, /* o : HVQ noise level */
Word16 *R, /* o : Bit allocation per sub band Q0 */
Word16 *Rsubband, /* o : Fractional bit allocation Q3 */
Word16 *sum, /* o : Sum of allocated shape bits Q0 */
Word16 *core_sfm, /* o : Last coded band in core Q0 */
const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_GEN Q0 */
)
{
Word16 i;
Word16 idx[NB_SFM];
Word16 wnorm[NB_SFM];
Word16 avrg_wnorm;
Word16 tmp, tmp2;
Word16 E_low;
Word16 E_hb_mean;
Word16 E_max;
Word16 i_max;
/* Temp */
Word16 sfm_limit = nb_sfm;
move16();
set16_fx( R, 0, NB_SFM);
FOR( i = 0; i < nb_sfm; i++ )
{
idx[i] = i;
move16();
}
test();
test();
test();
if( sub(hqswb_clas, HQ_TRANSIENT) != 0 && sub(hqswb_clas, HQ_HVQ) != 0 && !(sub(length, L_FRAME16k) == 0 && L_sub(core_brate, HQ_32k) == 0))
{
/* 'nf_idx' 2-bits index written later */
*num_bits = sub(*num_bits, 2);
}
test();
IF ( sub(hqswb_clas, HQ_GEN_SWB) == 0 || sub(hqswb_clas, HQ_GEN_FB) == 0 )
{
IF ( L_sub(core_brate, HQ_32k) == 0 )
{
*num_bits = sub(*num_bits, HQ_GENERIC_SWB_NBITS2 );
}
ELSE
{
*num_bits = sub(*num_bits, HQ_GENERIC_SWB_NBITS );
}
if ( sub(hqswb_clas, HQ_GEN_FB) == 0 )
{
*num_bits = sub(*num_bits, HQ_GENERIC_FB_NBITS );
}
}
IF( ( sub(length, L_FRAME48k) == 0 ) && (sub(hqswb_clas, HQ_HARMONIC) != 0) && (sub(hqswb_clas, HQ_HVQ) != 0))
{
tmp = 0;
move16();
if( sub(hqswb_clas,HQ_TRANSIENT) == 0 )
{
tmp = 1;
move16();
}
map_quant_weight_fx( normqlg2, wnorm, tmp );
}
ELSE
{
Copy( normqlg2, wnorm, nb_sfm );
}
IF( sub(hqswb_clas, HQ_HARMONIC) == 0 )
{
/* classification and limit bandwidth for bit allocation */
sfm_limit = sub(sfm_limit, 2);
limit_band_noise_level_calc_fx( wnorm, &sfm_limit, core_brate, noise_level );
/* Detect important band in high frequency region */
E_low = sum16_fx(wnorm, SFM_G1);
i_max = 0;
move16();
E_max = MIN16B;
move16();
E_hb_mean = 0;
move16();
FOR( i = SFM_G1; i < nb_sfm; i++)
{
E_hb_mean = add(E_hb_mean, wnorm[i]);
IF( sub(wnorm[i], E_max) > 0)
{
E_max = wnorm[i];
move16();
i_max = i;
move16();
}
}
E_hb_mean = shr(E_hb_mean, 4); /* Truncated division by SFM_G1 */
set16_fx( wnorm + sfm_limit, -20, sub(nb_sfm, sfm_limit) );
IF (L_msu0(L_deposit_l(E_low), E_max, 15) <= 0)
{
IF (L_msu(L_deposit_h(E_hb_mean), E_max, 21955) <= 0) /* 21955 = 0.67 (Q15) */
{
if (sub(i_max, sfm_limit) >= 0)
{
wnorm[i_max] = E_max;
move16();
}
}
}
}
test();
test();
test();
test();
IF( sub(hqswb_clas, HQ_HVQ) == 0 )
{
*sum = 0;
move16();
}
ELSE IF ( sub(hqswb_clas, HQ_GEN_SWB) == 0 || (sub(hqswb_clas, HQ_TRANSIENT) == 0 && sub(length, L_FRAME32k) == 0 && L_sub(core_brate, HQ_32k) <= 0) )
{
*sum = BitAllocF_fx( wnorm, core_brate, *num_bits, nb_sfm, R, Rsubband, hqswb_clas, num_env_bands );
}
ELSE IF( sub(length, L_FRAME16k) == 0 && L_sub(core_brate, HQ_32k) == 0 )
{
IF( sub(hqswb_clas, HQ_TRANSIENT) != 0 )
{
avrg_wnorm = wnorm[10];
move16();
FOR( i=11; i<18; i++ )
{
avrg_wnorm = add(avrg_wnorm, wnorm[i]);
}
avrg_wnorm = shr(avrg_wnorm, 3);
FOR( i=0; i<4; i++ )
{
if( sub(wnorm[i], avrg_wnorm) < 0 )
{
wnorm[i] = avrg_wnorm;
move16();
}
}
/* Estimate number of bits per band */
*sum = BitAllocWB_fx( wnorm, *num_bits, nb_sfm, R, Rsubband );
}
ELSE
{
reordvct_fx(wnorm, nb_sfm, idx);
bitalloc_fx( wnorm, idx, *num_bits, nb_sfm, QBIT_MAX2, R, sfmsize, hqswb_clas );
bitallocsum_fx( R, nb_sfm, sum, Rsubband, *num_bits, length, sfmsize );
}
}
ELSE
{
reordvct_fx(wnorm, nb_sfm, idx);
/* enlarge the wnorm value so that more bits can be allocated to (sfm_limit/2 ~ sfm_limit) range */
IF( sub(hqswb_clas, HQ_HARMONIC) == 0 )
{
tmp = shr(sfm_limit,1);
tmp2 = sub(tmp,1);
FOR( i=tmp; i<sfm_limit; i++ )
{
wnorm[i] = wnorm[tmp2];
move16();
}
}
bitalloc_fx( wnorm, idx, *num_bits, nb_sfm, QBIT_MAX2, R, sfmsize, hqswb_clas );
bitallocsum_fx( R, nb_sfm, sum, Rsubband, *num_bits, length, sfmsize );
}
/* Find last coded core band */
*core_sfm = sub(nb_sfm, 1);
test();
test();
IF( hqswb_clas == HQ_NORMAL || sub(hqswb_clas, HQ_HARMONIC) == 0 )
{
*core_sfm = find_last_band_fx(R, nb_sfm );
}
ELSE IF ( sub(hqswb_clas, HQ_GEN_SWB) == 0 || sub(hqswb_clas, HQ_GEN_FB) == 0 )
{
*core_sfm = find_last_band_fx( R, nb_sfm );
IF ( sub(*core_sfm ,num_env_bands) <0 )
{
*core_sfm = sub(num_env_bands,1);
}
}
*num_bits = sub(*num_bits, *sum);
return;
}
+279
View File
@@ -0,0 +1,279 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include "options.h"
#include "cnst_fx.h" /* Audio core constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
/*--------------------------------------------------------------------------*
* hq_configure()
*
* Configuration routine for HQ mode
*--------------------------------------------------------------------------*/
void hq_configure_fx(
const Word16 length, /* i : Frame length Q0 */
const Word16 hqswb_clas, /* i : HQ SWB class Q0 */
const Word32 core_brate, /* i : Codec bitrate Q0 */
Word16 *num_sfm, /* o : Total number of subbands Q0 */
Word16 *nb_sfm, /* o : Total number of coded bands Q0 */
Word16 *start_norm, /* o : First norm to be SDE encoded Q0 */
Word16 *num_env_bands, /* o : Number coded envelope bands Q0 */
Word16 *numnrmibits, /* o : Number of bits in fall-back norm encoding Q0 */
Word16 *hq_generic_offset, /* o : Freq offset for HQ GENERIC Q0 */
Word16 const **sfmsize, /* o : Subband bandwidths Q0 */
Word16 const **sfm_start, /* o : Subband start coefficients Q0 */
Word16 const **sfm_end /* o : Subband end coefficients Q0 */
)
{
*start_norm = 0;
move16();
IF ( sub(length, L_FRAME48k) == 0 )
{
IF ( sub(hqswb_clas, HQ_GEN_FB) == 0 )
{
*num_sfm = NB_SFM;
move16();
*sfmsize = band_len_HQ;
move16();
*sfm_start = band_start_HQ;
move16();
*sfm_end = band_end_HQ;
move16();
test();
IF ( L_sub(core_brate, HQ_32k) == 0 )
{
*hq_generic_offset = HQ_GENERIC_FOFFSET_32K;
move16();
}
ELSE IF ( L_sub(core_brate, HQ_16k40) == 0 || L_sub(core_brate, HQ_24k40) == 0 )
{
*hq_generic_offset = HQ_GENERIC_FOFFSET_24K4;
move16();
}
/* setting start frequency of FD BWE */
test();
IF ( L_sub(core_brate, HQ_32k) == 0 )
{
*num_env_bands = SFM_N_STA_10k;
move16();
}
ELSE IF ( L_sub(core_brate, HQ_16k40) == 0 || L_sub(core_brate, HQ_24k40) == 0 )
{
*num_env_bands = SFM_N_STA_8k;
move16();
}
*nb_sfm = *num_sfm;
move16();
}
ELSE
{
IF(sub(hqswb_clas, HQ_HARMONIC) == 0)
{
*num_sfm = SFM_N_HARM_FB;
move16();
*nb_sfm = SFM_N_HARM_FB;
move16();
*num_env_bands = SFM_N_HARM_FB;
move16();
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*sfm_end = band_end_harm;
move16();
}
ELSE IF ( sub(hqswb_clas, HQ_HVQ) == 0 )
{
IF ( L_sub(core_brate, HQ_24k40) == 0 )
{
*num_sfm = SFM_N_HARM_FB;
move16();
*nb_sfm = HVQ_THRES_SFM_24k;
move16();
*num_env_bands = sub(*num_sfm, *nb_sfm);
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*sfm_end = band_end_harm;
move16();
*start_norm = HVQ_THRES_SFM_24k;
move16();
}
ELSE
{
*num_sfm = SFM_N_HARM_FB;
move16();
*nb_sfm = HVQ_THRES_SFM_32k;
move16();
*num_env_bands = sub(*num_sfm, *nb_sfm);
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*start_norm = HVQ_THRES_SFM_32k;
move16();
*sfm_end = band_end_harm;
move16();
}
}
ELSE
{
*num_sfm = NB_SFM;
move16();
*nb_sfm = *num_sfm;
move16();
*num_env_bands = NB_SFM;
move16();
*sfmsize = band_len_HQ;
move16();
*sfm_start = band_start_HQ;
move16();
*sfm_end = band_end_HQ;
move16();
}
}
}
ELSE IF( sub(length, L_FRAME32k) == 0 )
{
IF ( sub(hqswb_clas, HQ_HARMONIC) == 0 )
{
*num_sfm = SFM_N_HARM;
move16();
*nb_sfm = SFM_N_HARM;
move16();
*num_env_bands = SFM_N_HARM;
move16();
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*sfm_end = band_end_harm;
move16();
}
ELSE IF ( sub(hqswb_clas, HQ_HVQ) == 0 )
{
IF ( L_sub(core_brate, HQ_24k40) == 0 )
{
*num_sfm = SFM_N_HARM;
move16();
*nb_sfm = HVQ_THRES_SFM_24k;
move16();
*num_env_bands = sub(*num_sfm, *nb_sfm);
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*sfm_end = band_end_harm;
move16();
*start_norm = HVQ_THRES_SFM_24k;
move16();
}
ELSE
{
*num_sfm = SFM_N_HARM;
move16();
*nb_sfm = HVQ_THRES_SFM_32k;
move16();
*num_env_bands = sub(*num_sfm, *nb_sfm);
*sfmsize = band_len_harm;
move16();
*sfm_start = band_start_harm;
move16();
*start_norm = HVQ_THRES_SFM_32k;
move16();
*sfm_end = band_end_harm;
move16();
}
}
ELSE IF ( sub(hqswb_clas, HQ_GEN_SWB) == 0 )
{
*num_sfm = SFM_N_SWB;
move16();
*sfmsize = band_len_HQ;
move16();
*sfm_start = band_start_HQ;
move16();
*sfm_end = band_end_HQ;
move16();
IF ( L_sub(core_brate, HQ_32k) == 0 )
{
*hq_generic_offset = HQ_GENERIC_FOFFSET_32K;
move16();
}
ELSE if ( L_sub(core_brate, HQ_24k40) == 0 )
{
*hq_generic_offset = HQ_GENERIC_FOFFSET_24K4;
move16();
}
/* setting start frequency of HQ Generic */
IF ( L_sub(core_brate, HQ_32k) == 0 )
{
*num_env_bands = SFM_N_STA_10k;
move16();
}
ELSE if( L_sub(core_brate, HQ_24k40) == 0 )
{
*num_env_bands = SFM_N_STA_8k;
move16();
}
*nb_sfm = *num_sfm;
move16();
}
ELSE
{
/* HQ_NORMAL and HQ_TRANSIENT */
*num_sfm = SFM_N_SWB;
move16();
*nb_sfm = *num_sfm;
move16();
*num_env_bands = SFM_N_SWB;
move16();
*sfmsize = band_len_HQ;
move16();
*sfm_start = band_start_HQ;
move16();
*sfm_end = band_end_HQ;
move16();
}
}
ELSE
{
*num_sfm = SFM_N_WB;
move16();
*nb_sfm = *num_sfm;
move16();
*num_env_bands = SFM_N_WB;
move16();
*sfmsize = band_len_wb;
move16();
*sfm_start = band_start_wb;
move16();
*sfm_end = band_end_wb;
move16();
}
*numnrmibits = extract_l(L_mult0(sub(*num_env_bands, 1), NORMI_BITS));
return;
}
File diff suppressed because it is too large Load Diff
+189
View File
@@ -0,0 +1,189 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h" /* required by wmc_tool */
#include "rom_com_fx.h"
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Common constants */
/*--------------------------------------------------------------------------*/
/* Function hvq_pvq_bitalloc */
/* ~~~~~~~~~~~~~~~~~~~~~~~~ */
/* */
/* Calculate the number of PVQ bands to code and allocate bits based on */
/* the number of available bits. */
/*--------------------------------------------------------------------------*/
Word16 hvq_pvq_bitalloc_fx(
Word16 num_bits, /* i/o: Number of available bits (including gain bits) */
const Word32 brate, /* i : bitrate */
const Word16 bwidth_fx, /* i : Encoded bandwidth */
const Word16 *ynrm, /* i : Envelope coefficients */
const Word32 manE_peak, /* i : Peak energy mantissa */
const Word16 expE_peak, /* i : Peak energy exponent */
Word16 *Rk, /* o : bit allocation for concatenated vector */
Word16 *R, /* i/o: Global bit allocation */
Word16 *sel_bands, /* o : Selected bands for encoding */
Word16 *n_sel_bands /* o : No. of selected bands for encoding */
)
{
Word16 num_bands, band_max_bits;
Word16 one_over_band_max_bits;
Word16 k;
Word16 reciprocal, envSum, expo, align, m, n, indx;
Word16 k_max;
Word16 k_start;
Word32 E_max, E_max5;
Word32 tmp, acc;
Word32 env_mean;
UWord16 lsb;
Word16 num_sfm;
IF (sub(bwidth_fx, FB) == 0)
{
num_sfm = SFM_N_HARM_FB;
}
ELSE
{
num_sfm = SFM_N_HARM;
}
IF ( L_sub(brate, HQ_24k40) == 0 )
{
band_max_bits = HVQ_BAND_MAX_BITS_24k;
move16();
one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_24k_FX;
move16();
k_start = HVQ_THRES_SFM_24k;
move16();
IF (sub(bwidth_fx, FB) == 0)
{
reciprocal = 2731; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16();
}
ELSE
{
reciprocal = 3277; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16();
}
}
ELSE
{
band_max_bits = HVQ_BAND_MAX_BITS_32k;
move16();
one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_32k_FX;
move16();
k_start = HVQ_THRES_SFM_32k;
move16();
IF (sub(bwidth_fx, FB) == 0)
{
reciprocal = 3641; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16();
}
ELSE
{
reciprocal = 4681; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16();
}
}
num_bands = mult( num_bits, one_over_band_max_bits ); /* Q0 */
num_bits = sub( num_bits, i_mult(num_bands, band_max_bits) ); /* Q0 */
IF ( sub(num_bits, HVQ_NEW_BAND_BIT_THR) >= 0 )
{
num_bands = add(num_bands, 1);
}
ELSE
{
num_bits = add(num_bits, band_max_bits);
}
/* safety check in case of bit errors */
if (sub(num_bands, 1) < 0)
{
return 0;
}
*n_sel_bands = 0;
move16();
envSum = 0;
move16();
E_max = L_deposit_l(0);
k_max = k_start;
move16();
FOR ( k = k_start; k < num_sfm; k++ )
{
indx = ynrm[k];
move16();
tmp = L_add(0,dicn_fx[indx]); /* Q14 */
envSum = add(envSum, indx); /* Since the size of dicn_fx = 40, ynrm[k] must be less than 41. 16 bits are enough for envSum.*/
IF (L_sub(tmp, E_max) > 0)
{
E_max = L_add(0,tmp);
k_max = k;
move16();
}
}
env_mean = L_mult(envSum, reciprocal); /* env_mean in Q16 */
IF (L_sub(L_sub(env_mean, L_deposit_h(ynrm[k_max])), 0x30000L) > 0) /* condition: env_mean - ynrm[k_max] > 3 */
{
expo = norm_l(E_max);
E_max = L_shl(E_max, expo);
Mpy_32_16_ss(E_max, 0x7a12, &E_max5, &lsb); /* NB: 5.0e5 = 0x7a12(Q15) x 2^19. */
/* True floating point value of E_max*5e5 = E_max5 x 2^(19 - expo - 14).
* In this context, the 32-bit E_max5 is in Q0, and
* -14 is due to Emax in Q14.
* True floating point value of E_peak = manE_peak x 2^(31 - expE_peak - 2*12). See peak_vq_enc_fx().
*/
/* Align the Q-points of the floating point Emax*5e5 and E_peak. */
align = sub(expo, expE_peak);
align = add(align, (19 - 14) - (31 - 2*12));
IF (align < 0)
{
acc = L_sub(E_max5, L_shl(manE_peak, align));
}
ELSE
{
acc = L_sub(L_shr(E_max5, align), manE_peak);
}
IF (acc > 0) /* condition: E_max*5.e5 > E_peak */
{
IF ( sub(band_len_harm[k_max], 96) == 0 )
{
n = 61;
}
ELSE
{
QuantaPerDsDirac_fx(band_len_harm[k_max], 1, hBitsN, &n);
}
m = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3);
IF (sub(m, n) >= 0)
{
IF (sub(num_bands, 1) > 0) /* condition: num_bands > 1 */
{
sel_bands[*n_sel_bands] = k_max;
move16();
*n_sel_bands = add(*n_sel_bands, 1);
R[k_max] = 1; /* Mark that the band has been encoded for fill_spectrum */ move16();
}
}
}
}
/* Allocate bits */
tmp = sub(num_bands,1);
FOR (k = 0; k < tmp; k++)
{
Rk[k] = shl(sub(band_max_bits, HVQ_PVQ_GAIN_BITS), 3);
move16();
}
/* NB: When it exits the above loop, k = num_bands - 1. */
Rk[k] = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3);
move16();
return num_bands;
}
+901
View File
@@ -0,0 +1,901 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <assert.h>
#include "options.h"
#include "stl.h"
#include "prot_fx.h"
#include "rom_com_fx.h"
#include "basop_util.h"
/**********************************************************************/ /*
returns an int val, multiplied with transFac
**************************************************************************/
static Word16 IGF_ApplyTransFac( /**< out: Q0 | multiplication factor */
const Word16 val, /**< in: Q15 | input value for multiplication, Q15 */
const Word16 transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */
)
{
Word16 ret;
if(sub(transFac, 0x4000) == 0)
{
return val;
}
ret = shl(val, 1);
ret = mac_r(0x00000000, ret, transFac);
ret = add(ret, s_and(ret, 1));
return ret;
}
/**********************************************************************/ /*
maps a given bitrate to the IGF_BITRATE index
**************************************************************************/
static Word16 IGF_MapBitRateToIndex( /**< out: Q0 | return bit rate index */
Word32 bitRate, /**< in: | bitrate */
Word16 mode /**< in: | bandwidth mode */
, Word16 rf_mode /**< in: | flag to signal the RF mode */
)
{
Word16 bitRateIndex;
bitRateIndex = IGF_BITRATE_UNKNOWN;
move16();
switch (mode)
{
case IGF_MODE_WB:
switch (bitRate)
{
case 13200:
if (sub(rf_mode,1) == 0)
{
bitRateIndex = IGF_BITRATE_RF_WB_13200;
}
break;
case 9600:
bitRateIndex = IGF_BITRATE_WB_9600;
break;
default:
assert(0);
}
break;
case IGF_MODE_SWB:
switch (bitRate)
{
case 9600:
bitRateIndex = IGF_BITRATE_SWB_9600;
break;
case 13200:
bitRateIndex = IGF_BITRATE_SWB_13200;
if (sub(rf_mode,1) == 0)
{
bitRateIndex = IGF_BITRATE_RF_SWB_13200;
}
break;
case 16400:
bitRateIndex = IGF_BITRATE_SWB_16400;
break;
case 24400:
bitRateIndex = IGF_BITRATE_SWB_24400;
break;
case 32000:
bitRateIndex = IGF_BITRATE_SWB_32000;
break;
case 48000:
bitRateIndex = IGF_BITRATE_SWB_48000;
break;
default:
assert(0);
}
break;
case IGF_MODE_FB:
switch (bitRate)
{
case 16400:
bitRateIndex = IGF_BITRATE_FB_16400;
break;
case 24400:
bitRateIndex = IGF_BITRATE_FB_24400;
break;
case 32000:
bitRateIndex = IGF_BITRATE_FB_32000;
break;
case 48000:
bitRateIndex = IGF_BITRATE_FB_48000;
break;
case 96000:
bitRateIndex = IGF_BITRATE_FB_96000;
break;
case 128000:
bitRateIndex = IGF_BITRATE_FB_128000;
break;
default:
assert(0);
}
break;
default:
assert(0);
}
return bitRateIndex;
}
/**********************************************************************/ /*
IGF grid setup
**************************************************************************/
static void IGF_gridSetUp(H_IGF_GRID hGrid, /**< out: | IGF grid handle */
Word16 bitRateIndex, /**< in: Q0 | IGF bitrate index */
Word32 sampleRate, /**< in: | sample rate */
Word16 frameLength, /**< in: | frame length */
Word16 transFac, /**< in: | transFac */
Word16 igfMinFq /**< in: | IGF minimum frequency indicating lower start frequency for copy up */
)
{
Word16 t;
Word16 sfb;
const Word16 *swb_offset;
Word16 swb_offset_len;
Word16 bandwidth;
Word16 wrp_sfb;
Word16 tmp1;
Word16 tmp2;
Word32 L_tmp1;
Word32 L_tmp2;
swb_offset = NULL;
move16();
swb_offset_len = 0;
move16();
SWITCH (bitRateIndex)
{
case IGF_BITRATE_WB_9600:
case IGF_BITRATE_SWB_9600:
case IGF_BITRATE_RF_WB_13200:
case IGF_BITRATE_RF_SWB_13200:
case IGF_BITRATE_SWB_13200:
case IGF_BITRATE_SWB_16400:
case IGF_BITRATE_SWB_24400:
case IGF_BITRATE_SWB_32000:
case IGF_BITRATE_SWB_48000:
swb_offset = &swb_offset_LB_new[bitRateIndex][1];
swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
move16();
Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
BREAK;
case IGF_BITRATE_FB_16400:
case IGF_BITRATE_FB_24400:
case IGF_BITRATE_FB_32000:
swb_offset = &swb_offset_LB_new[bitRateIndex][1];
swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
move16();
Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
BREAK;
case IGF_BITRATE_FB_48000:
case IGF_BITRATE_FB_96000:
case IGF_BITRATE_FB_128000:
swb_offset = &swb_offset_LB_new[bitRateIndex][1];
swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
move16();
Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
BREAK;
case IGF_BITRATE_UNKNOWN:
default:
assert(0);
}
FOR(sfb = 0; sfb < swb_offset_len; sfb++)
{
hGrid->swb_offset[sfb] = IGF_ApplyTransFac(swb_offset[sfb], transFac);
move16();
}
hGrid->infoIsRefined = 0;
move16();
frameLength = IGF_ApplyTransFac(frameLength, transFac);
tmp2 = norm_s(frameLength);
bandwidth = shl(frameLength,tmp2);
hGrid->swb_offset_len = extract_l(L_shr(sampleRate, 2));
tmp1 = sub(norm_s(hGrid->swb_offset_len), 1);
hGrid->swb_offset_len = shl(hGrid->swb_offset_len, tmp1);
bandwidth = div_s(hGrid->swb_offset_len, bandwidth);
tmp2 = sub(add(tmp2, 1), tmp1);
bandwidth = shr(bandwidth, sub(15, tmp2));
hGrid->swb_offset_len = swb_offset_len;
move16();
hGrid->startSfb = 0;
move16();
hGrid->stopSfb = sub(hGrid->swb_offset_len, 1);
hGrid->startLine = hGrid->swb_offset[ hGrid->startSfb ];
move16();
hGrid->stopLine = hGrid->swb_offset[ hGrid->stopSfb ];
move16();
hGrid->startFrequency = imult1616(bandwidth, hGrid->startLine);
hGrid->stopFrequency = imult1616(bandwidth, hGrid->stopLine);
L_tmp1 = L_mult0(igfMinFq, frameLength);
tmp1 = sub(norm_l(L_tmp1), 1);
L_tmp1 = L_shl(L_tmp1, tmp1);
tmp2 = norm_l(sampleRate);
L_tmp2 = L_shl(sampleRate, tmp2);
tmp1 = add(WORD16_BITS-1, sub(tmp1, add(tmp2, 1))); /* takes into account sampleRate >> 1 */
hGrid->minSrcSubband = div_s(extract_h(L_tmp1), extract_h(L_tmp2));
hGrid->minSrcSubband = shr(hGrid->minSrcSubband, tmp1);
hGrid->minSrcSubband = add(hGrid->minSrcSubband, s_and(hGrid->minSrcSubband, 1));
hGrid->minSrcFrequency = imult1616(bandwidth, hGrid->minSrcSubband);
hGrid->infoGranuleLen = frameLength;
move16();
hGrid->infoTransFac = transFac;
move16();
hGrid->sfbWrap[0] = 0;
move16();
hGrid->tile[0] = hGrid->startLine;
move16();
/*************************************************************************/
SWITCH (bitRateIndex)
{
/* SWB 13200 */
case IGF_BITRATE_WB_9600:
hGrid->nTiles = 2;
move16();
wrp_sfb = 2;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[1] = hGrid->minSrcSubband;
move16();
hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_RF_WB_13200:
hGrid->nTiles = 2;
wrp_sfb = 2;
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
hGrid->sbWrap[0] = hGrid->minSrcSubband;
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
/*2nd*/
hGrid->sfbWrap[1+1] = hGrid->stopSfb;
hGrid->sbWrap[1] = hGrid->minSrcSubband;
hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
BREAK;
case IGF_BITRATE_SWB_9600:
hGrid->nTiles = 3;
wrp_sfb = 1;
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
hGrid->sbWrap[0] = hGrid->minSrcSubband;
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
/*2nd*/
wrp_sfb = 2;
hGrid->sfbWrap[1+1] = wrp_sfb;
hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
/*3rd*/
hGrid->sfbWrap[2+1] = hGrid->stopSfb;
hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac);
hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
BREAK;
case IGF_BITRATE_RF_SWB_13200:
hGrid->nTiles = 3;
wrp_sfb = 1;
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
hGrid->sbWrap[0] = hGrid->minSrcSubband;
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
/*2nd*/
wrp_sfb = 2;
hGrid->sfbWrap[1+1] = wrp_sfb;
hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
/*3rd*/
hGrid->sfbWrap[2+1] = hGrid->stopSfb;
hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac);
hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
BREAK;
case IGF_BITRATE_SWB_13200:
hGrid->nTiles = 2;
move16();
wrp_sfb = 4;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac));
move16();
hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_SWB_16400:
hGrid->nTiles = 3;
move16();
wrp_sfb = 4;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = 6;
move16();
hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(48, transFac));
move16();
hGrid->tile[1+1] = hGrid->swb_offset[6];
move16();
/*3nd*/
hGrid->sfbWrap[2+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[2] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(64, transFac));
move16();
hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_SWB_24400:
case IGF_BITRATE_SWB_32000:
hGrid->nTiles = 3;
move16();
wrp_sfb = 4;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = 7;
move16();
hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac));
move16();
hGrid->tile[1+1] = hGrid->swb_offset[7];
move16();
/*3nd*/
hGrid->sfbWrap[2+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[2] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(64, transFac));
move16();
hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_SWB_48000:
hGrid->nTiles = 1;
move16();
wrp_sfb = hGrid->stopSfb;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[0] = sub(shl(hGrid->startLine, 1), hGrid->stopLine);
move16();
hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_FB_16400:
hGrid->nTiles = 3;
move16();
wrp_sfb = 4;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
wrp_sfb = 7;
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = wrp_sfb;
move16();
hGrid->sbWrap[1] = hGrid->minSrcSubband;
move16();
hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*3nd*/
hGrid->sfbWrap[2+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[2] = hGrid->minSrcSubband;
move16();
hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_FB_24400:
case IGF_BITRATE_FB_32000:
hGrid->nTiles = 4;
move16();
wrp_sfb = 4;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = wrp_sfb;
move16();
hGrid->sbWrap[0] = hGrid->minSrcSubband;
move16();
hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
move16();
wrp_sfb = 6;
move16();
/*2nd*/
hGrid->sfbWrap[1+1] = wrp_sfb;
move16();
hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac));
move16();
hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
move16();
wrp_sfb = 9;
move16();
/*3nd*/
hGrid->sfbWrap[2+1] = wrp_sfb;
move16();
hGrid->sbWrap[2] = hGrid->minSrcSubband;
move16();
hGrid->tile[2+1] = hGrid->swb_offset[wrp_sfb];
move16();
/*4nd*/
hGrid->sfbWrap[3+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[3] = add(hGrid->minSrcSubband, sub(hGrid->swb_offset[9], hGrid->swb_offset[8]));
move16();
hGrid->tile[3+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
case IGF_BITRATE_FB_48000:
case IGF_BITRATE_FB_96000:
case IGF_BITRATE_FB_128000:
hGrid->nTiles = 1;
move16();
/*1st*/
hGrid->sfbWrap[0+1] = hGrid->stopSfb;
move16();
hGrid->sbWrap[0] = sub(shl(hGrid->startLine, 1), hGrid->stopLine);
move16();
hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb];
move16();
BREAK;
default:
assert(0);
}/*switch*/
/*************************************************************************/
/*************************************************************************/
/* adapt level envelope: */
SWITCH (bitRateIndex)
{
case IGF_BITRATE_RF_WB_13200:
case IGF_BITRATE_WB_9600:
hGrid->gFactor = 13107/*0.80f Q14*/;
move16();
hGrid->fFactor = 11469/*0.70f Q14*/;
move16();
hGrid->lFactor = 9830/*0.60f Q14*/;
move16();
BREAK;
case IGF_BITRATE_SWB_13200:
case IGF_BITRATE_FB_16400:
case IGF_BITRATE_SWB_16400:
hGrid->gFactor = 15237/*0.93f Q14*/;
move16();
hGrid->fFactor = 3277/*0.20f Q14*/;
move16();
hGrid->lFactor = 13926/*0.85f Q14*/;
move16();
BREAK;
case IGF_BITRATE_FB_24400:
case IGF_BITRATE_SWB_24400:
case IGF_BITRATE_FB_32000:
case IGF_BITRATE_SWB_32000:
hGrid->gFactor = 15811/*0.965f Q14*/;
move16();
hGrid->fFactor = 3277/*0.20f Q14*/;
move16();
hGrid->lFactor = 13926/*0.85f Q14*/;
move16();
BREAK;
case IGF_BITRATE_FB_48000:
case IGF_BITRATE_SWB_48000:
hGrid->gFactor = 16384/*1.00f Q14*/;
move16();
hGrid->fFactor = 3277/*0.20f Q14*/;
move16();
hGrid->lFactor = 16384/*1.00f Q14*/;
move16();
BREAK;
case IGF_BITRATE_SWB_9600:
case IGF_BITRATE_RF_SWB_13200:
default:
hGrid->gFactor = 16384/*1.00f Q14*/;
move16();
hGrid->fFactor = 0/*0.00f Q14*/;
move16();
hGrid->lFactor = 16384/*1.00f Q14*/;
move16();
}
FOR (t = add(hGrid->nTiles, 1); t < IGF_MAX_TILES; t++)
{
hGrid->tile[t] = 0;
move16();
hGrid->sbWrap[t - 1] = 0;
move16();
hGrid->sfbWrap[t] = 0;
move16();
}
}
/**********************************************************************/ /*
calculates energy per sfb via power spectrum
**************************************************************************/
void IGFCommonFuncsCalcSfbEnergyPowerSpec(const Word16 startSfb, /**< in: Q0 | start sfb index */
const Word16 stopSfb, /**< in: Q0 | stop sfb index */
const Word16 *swb_offset, /**< in: Q0 | IGF swb offset table */
Word32 *pPowerSpectrum, /**< in: Q31 | power spectrum */
Word16 *pPowerSpectrum_exp, /**< in: | Exponent of PowerSpectrum */
Word32 *sfbEnergy, /**< out:Q31 | SFB energies , will be initialized inside this function */
Word16 *sfbEnergy_exp /**< out: | Exponent of PowerSpectrum */
)
{
Word16/*Q0*/ sfb;
Word16/*Q0*/ line;
Word32 L_c;
FOR (sfb = startSfb; sfb < stopSfb; sfb++)
{
sfbEnergy[sfb] = L_deposit_l(0);
}
IF (NULL == pPowerSpectrum)
{
return;
}
FOR (sfb = startSfb; sfb < stopSfb; sfb++)
{
L_c = L_deposit_l(0);
FOR (line = swb_offset[sfb]; line < swb_offset[sfb+1]; line++)
{
Carry = 0;
sfbEnergy[sfb] = L_add_c(sfbEnergy[sfb], pPowerSpectrum[line]);
move32();
Overflow = 0;
L_c = L_macNs(L_c,0,0);
}
sfbEnergy[sfb] = norm_llQ31(L_c,sfbEnergy[sfb],&(sfbEnergy_exp[sfb]));
move32();
sfbEnergy_exp[sfb] = add(sfbEnergy_exp[sfb],*pPowerSpectrum_exp);
move16();
}
}
/**********************************************************************/ /*
calculate the MDCT square spectrum in the IGF range
**************************************************************************/
void IGFCommonFuncsMDCTSquareSpec(const Word16 sqrtBgn, /**< in: Q0 | start MDCT subband index */
const Word16 sqrtEnd, /**< in: Q0 | stop MDCT subband index */
const Word32 *mdctSpec, /**< in: Q31 | MDCT spectrum to square */
const Word16 mdctSpec_e, /**< in: | exponent of mdctSpectrum */
Word32 *mdctSquareSpec, /**< out:Q31 | MDCT square spectrum */
Word16 *mdctSquareSpec_e, /**< out: | exponent of mdctSquareSpec */
Word16 indexOffset /**< in: Q0 | index offset */
)
{
Word16 i;
Word16 j;
Word16 s1;
Word16 tmp;
/* get headroom, only in IGF range */
s1 = getScaleFactor32(mdctSpec + sqrtBgn, sub(sqrtEnd, sqrtBgn));
/* set new exponent */
*mdctSquareSpec_e = add(shl(sub(mdctSpec_e, s1), 1), 1);
move16();
/* MDCT square spectrum: MDCT^2 */
j = add(sqrtBgn, indexOffset); /* handle indexOffset with care, otherwise memory overruns may occur! */
FOR (i = sqrtBgn; i < sqrtEnd; i++)
{
tmp = round_fx(L_shl(mdctSpec[i], s1));
mdctSquareSpec[j++] = L_mult0(tmp, tmp);
move32();
}
}
/**********************************************************************/ /*
write bits to stream
**************************************************************************/
void IGFCommonFuncsWriteSerialBit(void *st, /**< in: | encoder/decoder state structure */
Word16 *pBitOffset, /**< out: Q0 | bit offset */
Word16 bit /**< in: Q0 | value of bit */
)
{
IF (st)
{
push_next_indice_fx((Encoder_State_fx*)st, bit, 1);
}
*pBitOffset = add(*pBitOffset, 1);
move16();
return;
}
/**********************************************************************/ /*
changes the IGF configuration
**************************************************************************/
Word16 IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */
Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */
Word16 mode, /**< in: Q0 | bandwidth mode */
H_IGF_INFO hIGFInfo /**< out: | IGF info handle */
,Word16 rf_mode /**< in: flag to signal the RF mode */
)
{
H_IGF_GRID hGrid;
Word16 retValue;
Word32 sampleRate;
Word16 frameLength;
Word16 igfMinFq;
Word16 maxHopsize;
retValue = 0; /* bitrate index is unknown -> error! */ move16();
/* interface call for reading in settings */
hIGFInfo->bitRateIndex = IGF_MapBitRateToIndex(bitRate, mode
,rf_mode
);
IF (sub(hIGFInfo->bitRateIndex, IGF_BITRATE_UNKNOWN) != 0)
{
retValue = 1; /* no error */ move16();
/* mapping to local values */
sampleRate = igfMode[hIGFInfo->bitRateIndex].sampleRate;
move32();
frameLength = igfMode[hIGFInfo->bitRateIndex].frameLength;
move16();
igfMinFq = igfMode[hIGFInfo->bitRateIndex].igfMinFq;
move16();
maxHopsize = igfMode[hIGFInfo->bitRateIndex].maxHopsize;
move16();
/* basic information */
hIGFInfo->sampleRate = sampleRate;
move32();
hIGFInfo->frameLength = frameLength;
move16();
hIGFInfo->maxHopsize = maxHopsize;
move16();
hIGFInfo->nfSeed = 0;
move16();
/* set up regular IGF grid for TCX 20 (transfac = 1.f) */
hGrid = &hIGFInfo->grid[IGF_GRID_LB_NORM];
IGF_gridSetUp(hGrid,
hIGFInfo->bitRateIndex,
sampleRate,
frameLength,
16384/*1 Q14*/,
igfMinFq);
/* set up IGF grid for CELP->TCX 20 transitions (transfac = 1.25) */
hGrid = &hIGFInfo->grid[IGF_GRID_LB_TRAN];
IGF_gridSetUp(hGrid,
hIGFInfo->bitRateIndex,
sampleRate,
frameLength,
20480/*1.25 Q14*/,
igfMinFq);
/* set up IGF grid for TCX 10 (transfac = 0.5) */
hGrid = &hIGFInfo->grid[IGF_GRID_LB_SHORT];
IGF_gridSetUp(hGrid,
hIGFInfo->bitRateIndex,
sampleRate,
frameLength,
8192/*0.50f Q14*/,
igfMinFq);
}
return retValue;
}
/**********************************************************************/ /*
selects cumulative frequency tables and offsets for the IGF SCF arithmetic coder
**************************************************************************/
Word16 IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */
Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */
Word16 mode, /**< in: Q0 | bandwidth mode */
Word16 rf_mode, /**< in: | flag to signal the RF mode */
const Word16 **cf_se00, /**< out: | CF table for t == 0 and f == 0 */
const Word16 **cf_se01, /**< out: | CF table for t == 0 and f == 1 */
Word16 *cf_off_se01, /**< out: | offset for CF table above */
const Word16 **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */
const Word16 **cf_off_se02, /**< out: | offsets for CF tables above */
const Word16 **cf_se10, /**< out: | CF table for t == 1 and f == 0 */
Word16 *cf_off_se10, /**< out: | offset for CF table above */
const Word16 **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */
const Word16 **cf_off_se11 /**< out: | offsets for CF tables above */
)
{
Word16 retValue;
Word16 bitRateIndex;
retValue = 0; /* bitrate index is unknown -> error! */ move16();
bitRateIndex = IGF_MapBitRateToIndex(bitRate, mode
,rf_mode
);
IF (sub(bitRateIndex, IGF_BITRATE_UNKNOWN) != 0)
{
retValue = 1; /* no error */ move16();
SWITCH(bitRateIndex)
{
case IGF_BITRATE_WB_9600:
case IGF_BITRATE_RF_WB_13200:
case IGF_BITRATE_SWB_9600:
case IGF_BITRATE_SWB_13200:
case IGF_BITRATE_RF_SWB_13200:
case IGF_BITRATE_SWB_16400:
case IGF_BITRATE_SWB_24400:
case IGF_BITRATE_SWB_32000:
case IGF_BITRATE_SWB_48000:
*cf_se00 = cf_se00_tab;
*cf_se01 = cf_se01_tab[bitRateIndex];
*cf_off_se01 = cf_off_se01_tab[bitRateIndex];
*cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
move16();
*cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
move16();
*cf_se10 = &cf_se10_tab[0];
move16();
*cf_off_se10 = cf_off_se10_tab;
*cf_se11 = &cf_se11_tab[0][0][0];
move16();
*cf_off_se11 = &cf_off_se11_tab[0][0];
move16();
BREAK;
case IGF_BITRATE_FB_16400:
case IGF_BITRATE_FB_24400:
case IGF_BITRATE_FB_32000:
bitRateIndex = add(sub(bitRateIndex, IGF_BITRATE_FB_16400), IGF_BITRATE_SWB_16400);
*cf_se00 = cf_se00_tab;
*cf_se01 = cf_se01_tab[bitRateIndex];
*cf_off_se01 = cf_off_se01_tab[bitRateIndex];
*cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
move16();
*cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
move16();
*cf_se10 = &cf_se10_tab[0];
move16();
*cf_off_se10 = cf_off_se10_tab;
*cf_se11 = &cf_se11_tab[0][0][0];
move16();
*cf_off_se11 = &cf_off_se11_tab[0][0];
move16();
BREAK;
case IGF_BITRATE_FB_48000:
bitRateIndex = add(sub(bitRateIndex, IGF_BITRATE_FB_48000), IGF_BITRATE_SWB_48000);
*cf_se00 = cf_se00_tab;
*cf_se01 = cf_se01_tab[bitRateIndex];
*cf_off_se01 = cf_off_se01_tab[bitRateIndex];
*cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
move16();
*cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
move16();
*cf_se10 = &cf_se10_tab[0];
move16();
*cf_off_se10 = cf_off_se10_tab;
*cf_se11 = &cf_se11_tab[0][0][0];
move16();
*cf_off_se11 = &cf_off_se11_tab[0][0];
move16();
BREAK;
case IGF_BITRATE_FB_96000:
case IGF_BITRATE_FB_128000:
bitRateIndex = IGF_BITRATE_SWB_48000;
move16();
*cf_se00 = cf_se00_tab;
*cf_se01 = cf_se01_tab[bitRateIndex];
*cf_off_se01 = cf_off_se01_tab[bitRateIndex];
*cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
move16();
*cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
move16();
*cf_se10 = &cf_se10_tab[0];
move16();
*cf_off_se10 = cf_off_se10_tab;
*cf_se11 = &cf_se11_tab[0][0][0];
move16();
*cf_off_se11 = &cf_off_se11_tab[0][0];
move16();
BREAK;
case IGF_BITRATE_UNKNOWN:
default:
assert(0);
}
}
return retValue;
}
File diff suppressed because it is too large Load Diff
+173
View File
@@ -0,0 +1,173 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h"
/*========================================================================*/
/* FUNCTION : int_lsp4_fx() */
/*------------------------------------------------------------------------*/
/* PURPOSE : Interpolate LSPs find the A[z] parameters for all subframes */
/* by interpolating between old end-frame LSPs, current */
/* mid-frame LSPs and current end-frame LSPs */
/*------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) L_frame : length of the frame */
/* _ (Word16) m : order of LP filter */
/* _ (Word16) clas : signal frame class */
/* _ (Word16[]) lsp_old : LSPs from past frame Q15 */
/* _ (Word16[]) lsp_mid : LSPs from mid-frame Q15 */
/* _ (Word16[]) lsp_new : LSPs from present frame Q15 */
/*------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/*------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) Aq : LP coefficients in both subframes Q12 */
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*========================================================================*/
void int_lsp4_fx(
const Word16 L_frame, /* i : length of the frame */
const Word16 lsp_old[], /* i : LSPs from past frame Q15*/
const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/
const Word16 lsp_new[], /* i : LSPs from present frame Q15*/
Word16 *Aq, /* o : LP coefficients in both subframes Q12*/
const Word16 m, /* i : order of LP filter */
Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */
)
{
Word16 lsp[M16k];
Word16 i,j, k;
Word32 L_tmp;
const Word16 *pt_int_coeffs;
IF( sub(L_frame,L_FRAME) == 0)
{
IF ( sub(relax_prev_lsf_interp,1) == 0)
{
pt_int_coeffs = interpol_frac_mid_relaxprev_12k8_fx;
}
ELSE IF ( sub(relax_prev_lsf_interp,2) == 0 )
{
pt_int_coeffs = interpol_frac_mid_FEC_fx;
}
ELSE IF ( sub(relax_prev_lsf_interp,-1) == 0 )
{
pt_int_coeffs = interpol_frac_mid_relaxprev_pred_12k8_fx;
}
ELSE
{
pt_int_coeffs = interpol_frac_mid_fx;
}
}
ELSE /* L_frame == L_FRAME16k */
{
IF ( sub(relax_prev_lsf_interp,1) == 0 )
{
pt_int_coeffs = interpol_frac_mid_relaxprev_16k_fx;
}
ELSE IF ( sub(relax_prev_lsf_interp,2) == 0 )
{
pt_int_coeffs = interpol_frac_mid_16k_FEC_fx;
}
ELSE IF ( sub(relax_prev_lsf_interp,-1) == 0 )
{
pt_int_coeffs = interpol_frac_mid_relaxprev_pred_16k_fx;
}
ELSE
{
pt_int_coeffs = interpol_frac_mid_16k_fx;
}
}
k = sub(shr(L_frame,6),1);
FOR( j=0; j<k; j++ )
{
FOR( i=0; i<m; i++ )
{
L_tmp = L_mult(lsp_old[i], *pt_int_coeffs); /*Q31 */
L_tmp = L_mac(L_tmp, lsp_mid[i], *(pt_int_coeffs+1)); /*Q31 */
lsp[i] = mac_r(L_tmp, lsp_new[i], *(pt_int_coeffs+2));
move16();
}
pt_int_coeffs += 3;
move16();
E_LPC_f_lsp_a_conversion( lsp, Aq, m );
Aq += (m+1);
move16();
}
/* Last subframe */
E_LPC_f_lsp_a_conversion( lsp_new, Aq, m );
return;
}
/*---------------------------------------------------------------------*
* int_lsp_fx()
*
* Find the interpolated LSP parameters for all subframes
*---------------------------------------------------------------------*/
void int_lsp_fx(
const Word16 L_frame, /* i : length of the frame */
const Word16 lsp_old[], /* i : LSPs from past frame */
const Word16 lsp_new[], /* i : LSPs from present frame */
Word16 *Aq, /* o : LP coefficients in both subframes */
const Word16 m, /* i : order of LP filter */
const Word16 *int_coeffs, /* i : interpolation coefficients */
const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */
)
{
Word16 lsp[M], fnew, fold;
Word16 i, k;
const Word16 *pt_int_coeffs=NULL;
Word32 L_tmp;
Word16 tmp;
tmp = shr(L_frame,6); /*L_frame/L_SUBFR */
IF( sub(L_frame,L_FRAME) == 0 )
{
pt_int_coeffs = int_coeffs;
move16();
}
ELSE /* L_frame == L_FRAME16k */
{
pt_int_coeffs = interpol_frac_16k_fx;
}
FOR( k=0; k<tmp; k++ )
{
fnew = pt_int_coeffs[k];
move16();
fold = sub(32767, fnew); /* 1.0 - fac_new */
if (fold != 0)
fold = add(fold, 1);
FOR (i = 0; i < m; i++)
{
L_tmp = L_mult(lsp_old[i], fold);
L_tmp = L_mac(L_tmp, lsp_new[i], fnew);
if (fold == 0)
L_tmp = L_mac(L_tmp, lsp_new[i], 1); /* 'fnew' should have been 32768 */
lsp[i] = round_fx(L_tmp);
}
IF ( Opt_AMR_WB )
{
E_LPC_f_isp_a_conversion( lsp, Aq, m );
}
ELSE
{
E_LPC_f_lsp_a_conversion(lsp, Aq, m);
}
Aq +=(m+1);
}
return;
}
+189
View File
@@ -0,0 +1,189 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
/*--------------------------------------------------------------------------*
* interleave_spectrum_fx()
*
* Interleave the spectrum
*--------------------------------------------------------------------------*/
void interleave_spectrum_fx(
Word32 *coefs, /* i/o: input and output coefficients Q12 */
const Word16 length /* i : length of spectrum Q0 */
)
{
Word16 i, j, k;
Word32 *p1, *p2, *p3, *p4;
Word32 *p_out;
Word32 coefs_out[L_FRAME48k];
Word16 sublen[3] = {240, 160, 80};
Word16 grps;
const Word16 *bw;
const Word16 *cnt;
/* Common inits */
p1 = coefs;
p_out = coefs_out;
IF ( sub(length, L_FRAME48k) == 0 )
{
bw = intl_bw_48;
cnt = intl_cnt_48;
grps = N_INTL_GRP_48;
move16();
p2 = p1 + sublen[0];
p3 = p2 + sublen[0];
p4 = p3 + sublen[0];
}
ELSE IF( sub(length, L_FRAME32k) == 0 )
{
bw = intl_bw_32;
cnt = intl_cnt_32;
grps = N_INTL_GRP_32;
move16();
p2 = p1 + sublen[1];
p3 = p2 + sublen[1];
p4 = p3 + sublen[1];
}
ELSE /* length == L_FRAME16k */
{
bw = intl_bw_16;
cnt = intl_cnt_16;
grps = N_INTL_GRP_16;
move16();
p2 = p1 + sublen[2];
p3 = p2 + sublen[2];
p4 = p3 + sublen[2];
}
FOR (i = 0; i < grps; i++)
{
FOR (j = 0; j < cnt[i]; j++)
{
FOR (k = 0; k < bw[i]; k++)
{
*p_out++ = *p1++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p_out++ = *p2++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p_out++ = *p3++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p_out++ = *p4++;
move32();
}
}
}
/* For FB the interleaved spectrum is 800 samples */
Copy32(coefs_out, coefs, (Word16)(p_out - coefs_out));
return;
}
/*--------------------------------------------------------------------------*
* de_interleave_spectrum_fx()
*
* Deinterleave the spectrum
*--------------------------------------------------------------------------*/
void de_interleave_spectrum_fx(
Word32 *coefs, /* i/o: input and output coefficients Q12 */
const Word16 length /* i : length of spectrum Q0 */
)
{
Word16 i, j, k;
Word32 *p1, *p2, *p3, *p4;
Word32 *p_in;
Word32 coefs_out[L_FRAME48k];
Word16 sublen[] = {80, 160, 240, 320, 480, 720};
Word16 grps;
const Word16 *bw;
const Word16 *cnt;
/* common for all groups */
p1 = coefs_out;
IF ( sub(length, L_FRAME48k) == 0 )
{
bw = intl_bw_48;
cnt = intl_cnt_48;
grps = N_INTL_GRP_48;
move16();
p2 = coefs_out + sublen[2]; /* 240, length/4 */
p3 = coefs_out + sublen[4]; /* 480, 2*length/4 */
p4 = coefs_out + sublen[5]; /* 720, 3*length/4 */
}
ELSE IF( sub(length, L_FRAME32k) == 0 )
{
bw = intl_bw_32;
cnt = intl_cnt_32;
grps = N_INTL_GRP_32;
move16();
p2 = coefs_out + sublen[1]; /* 160 */
p3 = coefs_out + sublen[3]; /* 320 */
p4 = coefs_out + sublen[4]; /* 480 */
}
ELSE /* length == L_FRAME16k */
{
bw = intl_bw_16;
cnt = intl_cnt_16;
grps = N_INTL_GRP_16;
move16();
p2 = coefs_out + sublen[0]; /* 80 */
p3 = coefs_out + sublen[1]; /* 160 */
p4 = coefs_out + sublen[2]; /* 240 */
}
set32_fx(coefs_out, 0, L_FRAME48k);
p_in = coefs;
FOR (i = 0; i < grps; i++)
{
FOR (j = 0; j < cnt[i]; j++)
{
FOR (k = 0; k < bw[i]; k++)
{
*p1++ = *p_in++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p2++ = *p_in++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p3++ = *p_in++;
move32();
}
FOR (k = 0; k < bw[i]; k++)
{
*p4++ = *p_in++;
move32();
}
}
}
Copy32(coefs_out, coefs, length);
return;
}
+80
View File
@@ -0,0 +1,80 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* tables definition */
#include "stl.h"
Word32 Interpol_lc_fx( /* o : interpolated value Qx+16 */
const Word16 *x, /* i : input vector Q0 */
const Word16 *win, /* i : interpolation window Q14 */
const Word16 frac, /* i : fraction (0..up_samp) Q0 */
const Word16 up_samp, /* i : upsampling factor Q0 */
const Word16 nb_coef /* i : number of coefficients Q0 */
)
{
Word16 i;
const Word16 *c1, *c2, *x2;
Word32 L_sum;
x2 = &x[1];
c1 = &win[frac];
c2 = &win[sub(up_samp,frac)];
L_sum = L_mult0(*x--, *c1);
L_sum = L_mac0(L_sum, *x2++, *c2);
FOR (i=1; i<nb_coef; i++)
{
c2 += up_samp; /* move16() not needed, since the coefficient can be rearrange in bit exact way */
c1 += up_samp;
/* Using L_mac0 limits the risk of saturation during the loop, saturation may occures after the loop */
if (*c1)
{
L_sum = L_mac0(L_sum, *x, *c1);
}
--x;
if (*c2)
{
L_sum = L_mac0(L_sum, *x2, *c2);
}
++x2;
}
L_sum = L_shl(L_sum,1);
return L_sum;
}
/*--------------------------------------------------------------------------*
* Interpol_4()
*
* For interpolating the normalized correlation with 1/4 resolution.
*--------------------------------------------------------------------------*/
Word16 Interpol_4( /* o : interpolated value */
Word16 * x, /* i : input vector */
Word16 frac /* i : fraction (-4..+3) */
)
{
Word16 i;
Word32 L_sum;
x = x - L_INTERPOL1 + 1;
L_sum = L_mult(x[0], (inter4_1_fx+UP_SAMP-1)[-frac]);
FOR (i = 1; i < 2 * L_INTERPOL1; i++)
{
/*
* Here, additions with UP_SAMP are not counted
* because, the window could easily be modified
* so that the values needed are contiguous.
*/
frac -= UP_SAMP;
L_sum = L_mac(L_sum, x[i], (inter4_1_fx+UP_SAMP-1)[-frac]);
}
BASOP_SATURATE_WARNING_OFF
/* Here, saturation might occur by intention */
L_sum = L_shl(L_sum,1);
BASOP_SATURATE_WARNING_ON
return round_fx(L_sum);
}
+329
View File
@@ -0,0 +1,329 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#ifdef _MSC_VER
void E_LPC_isf_isp_conversion(const Word16 isf[], Word16 isp[], const Word16 m);
#endif
/*---------------------------------------------------------------------*
* isf_dec_amr_wb()
*
* Decoding of ISF parameters in AMR-WB IO mode
*---------------------------------------------------------------------*/
void isf_dec_amr_wb_fx(
Decoder_State_fx *st, /* i/o: State structure */
Word16 *Aq, /* o : quantized A(z) for 4 subframes */
Word16 *isf_new, /* o : de-quantized ISF vector */
Word16 *isp_new /* o : de-quantized ISP vector */
)
{
Word16 i;
Word16 indice[7];
Word32 L_tmp;
set16_fx( indice, -1, 7 );
/*---------------------------------*
* ISF de-quantization of SID frames
*---------------------------------*/
IF ( L_sub(st->core_brate_fx,SID_1k75) == 0 )
{
indice[0] = (Word16)get_next_indice_fx( st, 6 );
move16();
indice[1] = (Word16)get_next_indice_fx( st, 6 );
move16();
indice[2] = (Word16)get_next_indice_fx( st, 6 );
move16();
indice[3] = (Word16)get_next_indice_fx( st, 5 );
move16();
indice[4] = (Word16)get_next_indice_fx( st, 5 );
move16();
disf_ns_28b_fx( indice, isf_new );
reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2);
E_LPC_isf_isp_conversion( isf_new, isp_new, M);
/* return if SID frame (conversion to A(z) done in the calling function) */
return;
}
/*-----------------------------------------------------------------*
* ISF de-quantization of all other frames
*-----------------------------------------------------------------*/
IF( L_sub(st->core_brate_fx,ACELP_6k60) == 0 )
{
indice[0] = (Word16)get_next_indice_fx( st, 8 );
move16();
indice[1] = (Word16)get_next_indice_fx( st, 8 );
move16();
indice[2] = (Word16)get_next_indice_fx( st, 7 );
move16();
indice[3] = (Word16)get_next_indice_fx( st, 7 );
move16();
indice[4] = (Word16)get_next_indice_fx( st, 6 );
move16();
disf_2s_36b_fx( indice, isf_new, st->mem_AR_fx, st->mem_MA_fx, 1 );
}
ELSE
{
indice[0] = (Word16)get_next_indice_fx( st, 8 );
move16();
indice[1] = (Word16)get_next_indice_fx( st, 8 );
move16();
indice[2] = (Word16)get_next_indice_fx( st, 6 );
move16();
indice[3] = (Word16)get_next_indice_fx( st, 7 );
move16();
indice[4] = (Word16)get_next_indice_fx( st, 7 );
move16();
indice[5] = (Word16)get_next_indice_fx( st, 5 );
move16();
indice[6] = (Word16)get_next_indice_fx( st, 5 );
move16();
disf_2s_46b_fx( indice, isf_new, st->mem_AR_fx, st->mem_MA_fx,1 );
}
reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2 );
/* convert quantized ISFs to ISPs */
E_LPC_isf_isp_conversion( isf_new, isp_new, M);
/*-------------------------------------------------------------------------------------*
* FEC - update adaptive mean ISF vector
*-------------------------------------------------------------------------------------*/
FOR ( i=0; i<M; i++ )
{
/*st->lsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + isf_new[i]) / 3;*/
L_tmp = L_mult(st->lsfoldbfi1_fx[i], 10923);
L_tmp = L_mac(L_tmp, st->lsfoldbfi0_fx[i], 10923);
st->lsf_adaptive_mean_fx[i] = round_fx(L_mac(L_tmp, isf_new[i], 10923));
}
/*-------------------------------------------------------------------------------------*
* ISP interpolation
* A(z) calculation
*-------------------------------------------------------------------------------------*/
if(st->rate_switching_reset)
{
/*extrapolation instead of interpolation*/
Copy(isp_new, st->lsp_old_fx, M);
Copy(isf_new, st->lsf_old_fx, M);
}
/* ISP interpolation and A(z) calculation */
int_lsp_fx( L_FRAME, st->lsp_old_fx, isp_new, Aq, M, interpol_isp_amr_wb_fx, 1 );
/*------------------------------------------------------------------*
* Check ISF stability : distance between old ISF and current ISF
*------------------------------------------------------------------*/
st->stab_fac_fx = lsf_stab_fx( isf_new, st->lsf_old_fx, 1, st->L_frame_fx );
return;
}
/*-------------------------------------------------------------------*
* disf_ns_28b()
*
* ISF de-quantizer for SID_1k75 frames (only for AMR-WB IO mode)
*-------------------------------------------------------------------*/
void disf_ns_28b_fx(
Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */
Word16 *isf_q /* o : ISF in the frequency domain (0..6400) */
)
{
Word16 i;
FOR (i = 0; i < 2; i++)
{
isf_q[i] = dico1_ns_28b_fx[indice[0]*2+i];
move16();
}
FOR (i = 0; i < 3; i++)
{
isf_q[i+2] = dico2_ns_28b_fx[indice[1]*3+i];
move16();
isf_q[i+5] = dico3_ns_28b_fx[indice[2]*3+i];
move16();
}
FOR (i = 0; i < 4; i++)
{
isf_q[i+8] = dico4_ns_28b_fx[indice[3]*4+i];
move16();
isf_q[i+12] = dico5_ns_28b_fx[indice[4]*4+i];
move16();
}
FOR (i=0; i<M; i++)
{
isf_q[i] = add(isf_q[i] , mean_isf_noise_amr_wb_fx[i]);
move16();
}
return;
}
/*-------------------------------------------------------------------*
* disf_2s_46b()
*
* ISF de-quantizer for 46b. codebooks (only for AMR-WB IO mode)
*-------------------------------------------------------------------*/
void disf_2s_46b_fx(
Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */
Word16 *isf_q, /* o : quantized ISFs in the cosine domain */
Word16 *mem_AR, /* o : quantizer memory for AR model */
Word16 *mem_MA, /* i/o: quantizer memory for MA model */
const Word16 enc_dec /* i : encoder (0), decoder (1) G722.2 FER */
)
{
Word16 i;
IF (enc_dec != 0) /* Redirection for G722.2 compatibility */
{
i = 0;
move16();
WHILE (sub(Indirect_dico1[i], indice[0]) != 0)
{
i = add(i, 1);
}
indice[0] = i;
move16();
}
FOR (i = 0; i < 9; i++)
{
isf_q[i] = dico1_isf_fx[indice[0]*9+i];
move16();
}
FOR (i = 0; i < 7; i++)
{
isf_q[i+9] = dico2_isf_fx[indice[1]*7+i];
move16();
}
FOR (i = 0; i < 3; i++)
{
isf_q[i] = add(isf_q[i],dico21_isf_46b_fx[indice[2]*3+i]);
move16();
isf_q[i+3] = add(isf_q[i+3], dico22_isf_46b_fx[indice[3]*3+i]);
move16();
isf_q[i+6] = add(isf_q[i+6], dico23_isf_46b_fx[indice[4]*3+i]);
move16();
isf_q[i+9] = add(isf_q[i+9], dico24_isf_46b_fx[indice[5]*3+i]);
move16();
}
FOR (i = 0; i < 4; i++)
{
isf_q[i+12] = add(isf_q[i+12], dico25_isf_46b_fx[indice[6]*4+i]);
move16();
}
FOR (i = 0; i < M; i++)
{
mem_AR[i] = add(isf_q[i], mult_r(MU_MA_FX, mem_MA[i]));
move16(); /* Update with quantized ISF vector for AR model */
mem_MA[i] = isf_q[i];
move16(); /* Update with quantized prediction error for MA model */
isf_q[i] = add(mem_AR[i], mean_isf_amr_wb_fx[i]);
move16(); /* Quantized ISFs */
}
return;
}
/*-------------------------------------------------------------------*
* disf_2s_36b()
*
* ISF de-quantizer for 36b. codebooks (only for AMR-WB IO mode)
*-------------------------------------------------------------------*/
void disf_2s_36b_fx(
Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */
Word16 *isf_q, /* o : quantized ISFs in the cosine domain */
Word16 *mem_AR, /* i/o: quantizer memory for AR model */
Word16 *mem_MA, /* i/o: quantizer memory for MA model */
const Word16 enc_dec /* i : encoder (0), decoder (1) G722.2 FER */
)
{
Word16 i;
const Word16 *pt_dico1;
IF (enc_dec != 0) /* Redirection for G722.2 interoperability */
{
i = 0;
move16();
WHILE (sub(Indirect_dico1[i], indice[0]) != 0)
{
i = add(i,1);
}
indice[0] = i;
move16();
}
pt_dico1 = dico1_isf_fx; /* Pointer of the 1st stage, 1st plit */
FOR (i = 0; i < 9; i++)
{
isf_q[i] = pt_dico1[indice[0]*9+i];
move16();
}
FOR (i = 0; i < 7; i++)
{
isf_q[i+9] = dico2_isf_fx[indice[1]*7+i];
move16();
}
FOR (i = 0; i < 5; i++)
{
isf_q[i] = add(isf_q[i], dico21_isf_36b_fx[indice[2]*5+i]);
move16();
}
FOR (i = 0; i < 4; i++)
{
isf_q[i+5] = add(isf_q[i+5], dico22_isf_36b_fx[indice[3]*4+i]);
move16();
}
FOR (i = 0; i < 7; i++)
{
isf_q[i+9] = add(isf_q[i+9], dico23_isf_36b_fx[indice[4]*7+i]);
move16();
}
FOR (i = 0; i < M; i++)
{
mem_AR[i] = add(isf_q[i], mult_r(MU_MA_FX, mem_MA[i]));
move16(); /* Update with quantized ISF vector for AR model */
mem_MA[i] = isf_q[i];
move16(); /* Update with quantized prediction error for MA model */
isf_q[i] = mem_AR[i] + mean_isf_amr_wb_fx[i];
move16(); /* Quantized ISFs */
}
return;
}
+130
View File
@@ -0,0 +1,130 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "prot_fx.h"
#include "rom_com_fx.h"
#include "basop_util.h"
#include "stl.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
#define kLagWinThGain1 19661 /* 0.6f in Q15 */
#define kLagWinThGain2 9830 /* 0.3f in Q15 */
/*-------------------------------------------------------------*
* procedure lag_wind: *
* ~~~~~~~~~ *
* lag windowing of the autocorrelations *
*-------------------------------------------------------------*/
void lag_wind(
Word16 r_h[], /* in/out: autocorrelations */
Word16 r_l[], /* in/out: autocorrelations */
Word16 m, /* input : order of LP filter */
Word32 sr, /* input : sampling rate */
Word16 strength /* input : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */
)
{
Word16 i;
Word32 tmp;
const Word16 *wnd_h, *wnd_l;
assert(0 <= strength && strength <= NUM_LAGW_STRENGTHS);
SWITCH (sr)
{
case 8000:
assert(m <= 16);
assert(strength == LAGW_STRONG);
wnd_h = lag_window_8k[0];
wnd_l = lag_window_8k[1];
BREAK;
case 12800:
assert(m <= 16);
wnd_h = lag_window_12k8[strength][0];
wnd_l = lag_window_12k8[strength][1];
BREAK;
case 16000:
assert(m <= 16);
wnd_h = lag_window_16k[strength][0];
wnd_l = lag_window_16k[strength][1];
BREAK;
case 24000:
case 25600:
assert(m <= 16);
wnd_h = lag_window_25k6[strength][0];
wnd_l = lag_window_25k6[strength][1];
BREAK;
case 32000:
assert(m <= 16);
wnd_h = lag_window_32k[strength][0];
wnd_l = lag_window_32k[strength][1];
BREAK;
case 48000:
assert(m <= 16);
assert(strength == LAGW_STRONG);
wnd_h = lag_window_48k[0];
wnd_l = lag_window_48k[1];
BREAK;
default:
assert(!"Lag window not implemented for this sampling rate");
return;
}
FOR (i = 1; i <= m; i++)
{
tmp = Mpy_32(r_h[i], r_l[i], wnd_h[i-1], wnd_l[i-1]);
L_Extract(tmp, &r_h[i], &r_l[i]);
}
}
void adapt_lag_wind(
Word16 r_h[], /* in/out: autocorrelations */
Word16 r_l[], /* in/out: autocorrelations */
Word16 m, /* input : order of LP filter */
const Word16 Top, /* input : open loop pitch lag */
const Word16 Tnc, /* input : open loop pitch gain */
Word32 sr /* input : sampling rate */
)
{
Word16 strength, pitch_lag;
Word16 pitch_gain;
pitch_lag = Top;
move16();
pitch_gain = Tnc;
move16();
IF (sub(pitch_lag, 80) < 0)
{
strength = LAGW_STRONG;
move16();
if (sub(pitch_gain, kLagWinThGain1) <= 0)
{
strength = LAGW_MEDIUM;
move16();
}
}
ELSE IF (sub(pitch_lag, 160) < 0)
{
strength = LAGW_MEDIUM;
move16();
if (sub(pitch_gain, kLagWinThGain2) <= 0)
{
strength = LAGW_WEAK;
move16();
}
}
ELSE
{
strength = LAGW_WEAK;
move16();
}
lag_wind(r_h, r_l, m, sr, strength);
}
+179
View File
@@ -0,0 +1,179 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "basop_util.h"
#include "prot_fx.h"
#include <assert.h>
#include "stl.h"
#define shift_e (16-1)
#define pos_e (16-1)
static void lerp_proc(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize);
void lerp(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize)
{
Word16 tmp1, tmp2, tmpexp;
BASOP_Util_Divide_MantExp(bufferNewSize, 0, bufferOldSize, 0, &tmp1, &tmpexp);
tmp1 = shr(tmp1,3); /*Q12*/
tmp1 = shl(tmp1,tmpexp);
BASOP_Util_Divide_MantExp(bufferOldSize, 0, bufferNewSize, 0, &tmp2, &tmpexp);
tmp2 = shr(tmp2,3); /*Q12*/
tmp2 = shl(tmp2,tmpexp);
test();
test();
IF(sub(tmp1,16224 /*3,9609375 in Q12*/) > 0)
{
Word16 tmpNewSize = shl(bufferOldSize,1);
WHILE(sub(bufferNewSize, bufferOldSize) > 0)
{
BASOP_Util_Divide_MantExp(bufferNewSize, 0, bufferOldSize, 0, &tmp1, &tmpexp);
tmp1 = shr(tmp1,3); /*Q12*/
tmp1 = shl(tmp1,tmpexp);
test();
IF(sub(tmp1,16224 /*3,9609375 in Q12*/) <= 0)
{
tmpNewSize = bufferNewSize;
}
lerp_proc(f, f_out, tmpNewSize, bufferOldSize);
f = f_out;
bufferOldSize = tmpNewSize;
tmpNewSize = shl(tmpNewSize,1);
}
}
ELSE IF(sub(tmp2,16224 /*3,9609375 in Q12*/) > 0)
{
Word16 tmpNewSize = shr(bufferOldSize,1);
WHILE(sub(bufferNewSize, bufferOldSize) < 0)
{
BASOP_Util_Divide_MantExp(bufferOldSize, 0, bufferNewSize, 0, &tmp2, &tmpexp);
tmp2 = shr(tmp2,3); /*Q12*/
tmp2 = shl(tmp2,tmpexp);
test();
IF(sub(tmp2,16224 /*3,9609375 in Q12*/) <= 0)
{
tmpNewSize = bufferNewSize;
}
lerp_proc(f, f_out, tmpNewSize, bufferOldSize);
f = f_out;
bufferOldSize = tmpNewSize;
tmpNewSize = shr(tmpNewSize,1);
}
}
else
{
lerp_proc(f, f_out, bufferNewSize, bufferOldSize);
}
}
void lerp_proc(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize)
{
Word16 i, idx, n;
Word16 diff;
Word32 pos, shift;
Word16 buf[2*L_FRAME_MAX];
Word16 *ptr;
ptr = f_out;
test();
test();
test();
if ( ((f <= f_out) && (f + bufferOldSize >= f_out)) || ((f_out <= f) && (f_out + bufferNewSize >= f)) )
{
ptr = buf;
move16();
}
IF( sub(bufferNewSize, bufferOldSize) == 0 )
{
Copy(f, f_out, bufferNewSize);
return;
}
shift = L_shl(L_deposit_l(div_s( bufferOldSize, shl(bufferNewSize, 4))), 4-shift_e+16);
pos = L_sub(L_shr(shift, 1), 32768l/*1.0f Q15*/);
/* Adjust interpolation shift to avoid accessing beyond end of input buffer. */
if ( L_sub(shift, 19661l/*0.3f Q16*/) < 0)
{
pos = L_sub(pos, 8520l/*0.13f Q16*/);
}
assert(pos_e == shift_e);
/* first point of interpolation */
IF (pos<0)
{
diff = shr(extract_l(pos), 1);
/*buf[0]=f[0]+pos*(f[1]-f[0]);*/
move16();
*ptr++ = add(f[0], msu_r(L_mult(diff, f[1]),diff, f[0]));
}
ELSE
{
idx=extract_h(pos);
diff = lshr(extract_l(pos), 1);
move16();
*ptr++ = add(f[idx], msu_r(L_mult(diff, f[idx+1]), diff, f[idx]));
}
pos = L_add(pos, shift);
idx = s_max(0, extract_h(pos));
n = sub(bufferNewSize, 1);
FOR ( i=1; i<n; i++ )
{
diff = lshr(extract_l(pos), 1);
if (pos < 0)
{
diff = sub(16384/*0.5f Q15*/, diff);
}
move16();
*ptr++ = add(f[idx], msu_r(L_mult(diff, f[idx+1]), diff, f[idx]));
pos = L_add(pos, shift);
idx = extract_h(pos);
}
/* last point */
if ( L_sub(pos, L_deposit_h(sub(bufferOldSize,1))) > 0 )
{
idx = sub(bufferOldSize,2);
}
assert(idx <= 2*L_FRAME_MAX);
/* diff = t - point;*/
diff = lshr(extract_l(L_shr(L_sub(pos, L_deposit_h(idx)), 1)), 1);
move16();
*ptr++ = add(f[idx], shl(msu_r(L_mult(diff, f[idx+1]), diff, f[idx]), 1));
test();
test();
test();
IF ( ((f <= f_out) && (f + bufferOldSize >= f_out)) || ((f_out <= f) && (f_out + bufferNewSize >= f)) )
{
Copy( buf, f_out, bufferNewSize );
}
}
+259
View File
@@ -0,0 +1,259 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
#include "rom_basop_util.h"
/*-------------------------------------------------*
* Local constants
*-------------------------------------------------*/
#define LIMIT_PIT_REL_LOWER 2 /* delta interval to extend pitch coding in relative Q */
#define LIMIT_PIT_REL_UPPER 0
/*-------------------------------------------------*
* limit_T0()
*
* Close-loop pitch lag search limitation
*-------------------------------------------------*/
void limit_T0_fx(
const Word16 L_frame, /* i : length of the frame */
const Word16 delta, /* i : Half the close-loop searched interval */
const Word16 pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */
const Word16 limit_flag, /* i : flag for Q limits (0=restrained, 1=extended) */
const Word16 T0, /* i : rough pitch estimate around which the search is done */
const Word16 T0_frac, /* i : pitch estimate fractional part */
Word16 *T0_min, /* o : lower pitch limit */
Word16 *T0_max /* o : higher pitch limit */
)
{
Word16 delta2,T1;
Word16 pit_min, pit_max;
IF( limit_flag == 0 ) /* restrained Q limits */
{
/* set limits */
IF( sub(L_frame,L_FRAME) == 0)
{
pit_max = PIT_MAX;
move16();
pit_min = PIT_MIN;
move16();
}
ELSE /* L_frame == L_FRAME16k */
{
pit_max = PIT16k_MAX;
move16();
pit_min = PIT16k_MIN;
move16();
}
delta2 = sub(shl(delta,1),1);
T1 = T0;
move16();
if( sub(T0_frac,2) >= 0 )
{
T1 = add(T1,1);
}
*T0_min = sub(T1,delta);
move16();
*T0_min = s_max(*T0_min,pit_min);
*T0_max = add(*T0_min,delta2);
move16();
IF( sub(*T0_max,pit_max) > 0)
{
*T0_max = pit_max;
move16();
*T0_min = sub(*T0_max,delta2);
move16();
}
}
ELSE /* extended Q limits */
{
/* set limits */
IF( sub(L_frame, L_FRAME) == 0)
{
pit_max = PIT_MAX;
move16();
pit_min = PIT_MIN_EXTEND;
move16();
if( sub(limit_flag, 2) == 0 )
{
pit_min = PIT_MIN_DOUBLEEXTEND;
move16();
}
}
ELSE /* L_frame == L_FRAME16k */
{
pit_max = PIT16k_MAX;
move16();
pit_min = PIT16k_MIN_EXTEND;
move16();
}
delta2 = sub(shl(delta,1),1) ;
move16();
T1 = T0;
move16();
if( sub(T0_frac,2) >= 0 )
{
T1 = add(T1,1);
}
*T0_min = sub(T1, delta);
move16();
IF( pit_flag == 0 )
{
/* subframes with absolute search: keep Q range */
*T0_min = s_max(*T0_min,pit_min);
*T0_max = add(*T0_min, delta2);
move16();
IF( sub(*T0_max,pit_max) > 0)
{
*T0_max = pit_max;
move16();
*T0_min = sub(*T0_max, delta2);
move16();
}
}
ELSE
{
/* subframes with relative search: extend Q range */
*T0_min = s_max(*T0_min,sub(pit_min, LIMIT_PIT_REL_LOWER));
move16();
*T0_min = s_max(*T0_min,L_INTERPOL);
*T0_max = *T0_min + delta2;
move16();
IF( sub(*T0_max, add(pit_max, LIMIT_PIT_REL_UPPER)) > 0 )
{
*T0_max = add(pit_max, LIMIT_PIT_REL_UPPER);
move16();
*T0_min = sub(*T0_max, delta2);
move16();
}
}
}
return;
}
#define inv_T0_res InvIntTable
/*-------------------------------------------------*
* Routine limit_T0_voiced()
*
* Close-loop pitch lag search limitation
*-------------------------------------------------*/
void limit_T0_voiced(
const Word16 nbits,
const Word16 res,
const Word16 T0, /* i : rough pitch estimate around which the search is done */
const Word16 T0_frac, /* i : pitch estimate fractional part */
const Word16 T0_res, /* i : pitch resolution */
Word16 *T0_min, /* o : lower pitch limit */
Word16 *T0_min_frac, /* o : lower pitch limit */
Word16 *T0_max, /* o : higher pitch limit */
Word16 *T0_max_frac, /* o : higher pitch limit */
const Word16 pit_min, /* i : Minimum pitch lag */
const Word16 pit_max /* i : Maximum pitch lag */
)
{
Word16 T1, temp1, temp2, res2;
assert(res > 1 && res<=6);
res2 = res;
move16();
if(sub(res,6) == 0)
{
res2 = shr(res2,1);
}
/* Mid-point */
T1 = T0;
test();
if( sub(T0_res,1) > 0 && sub(T0_frac,(shr(T0_res,1))) >= 0 )
{
T1 = add(T1,1);
}
/* Lower-bound */
temp1 = sub(i_mult(T1,res),shl(1,sub(nbits,1)));
temp2 = mult(temp1,inv_T0_res[res2]);
if(sub(res,6) == 0)
{
temp2 = shr(temp2,1);
}
*T0_min = temp2;
move16();
*T0_min_frac = sub(temp1,i_mult(temp2,res));
move16();
IF ( sub(*T0_min,pit_min) < 0)
{
*T0_min = pit_min;
move16();
*T0_min_frac = 0;
move16();
}
/* Higher-bound */
temp1 = add(i_mult(*T0_min,res),add(*T0_min_frac,sub(shl(1,nbits),1)));
temp2 = mult(temp1,inv_T0_res[res2]);
if(sub(res,6) == 0)
{
temp2 = shr(temp2,1);
}
*T0_max = temp2;
move16();
*T0_max_frac = sub(temp1,i_mult(temp2,res));
move16();
IF ( sub(*T0_max,pit_max) > 0)
{
*T0_max = pit_max;
move16();
*T0_max_frac = sub(res,1);
move16();
temp1 = add(i_mult(*T0_max,res),sub(*T0_max_frac,sub(shl(1,nbits),1)));
temp2 = mult(temp1,inv_T0_res[res2]);
if(sub(res,6) == 0)
{
temp2 = shr(temp2,1);
}
move16();
*T0_min = temp2;
*T0_min_frac = sub(temp1, i_mult(temp2,res));
move16();
}
return;
}
+195
View File
@@ -0,0 +1,195 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
#include "rom_com_fx.h" /* Static table prototypes */
#include "cnst_fx.h" /* Common constants */
/* Local constants */
#define THREN2POW 1518500250L
/*--------------------------------------------------------------------------*
* logqnorm_fx
*
* Log quantization for norms of sub-vectors
*--------------------------------------------------------------------------*/
void logqnorm_fx(
const Word32 *L_x, /* i : coefficient vector Qx */
const Word16 qx, /* i : Q value of input */
Word16 *k, /* o : index Q0 */
const Word16 L, /* i : codebook length Q0 */
const Word16 N, /* i : sub-vector size Q0 */
const Word16 hvq_flag /* i : HVQ flag Q0 */
)
{
Word16 i, m;
Word16 coefs_shift, power_shift, temp_shift;
Word32 L_temp, L_temp1, L_temp2;
Word16 coefs16[MAX_SFM_LEN_FX];
UWord16 lsb;
Word16 offset = add(3,shl(qx,1)); /* 3 + 2*qx */
lsb = 0U; /* to avoid compilation warnings */
L_temp1 = L_deposit_l(1);
FOR (i=0; i<N; i++)
{
L_temp2 = L_abs(L_x[i]);
L_temp1 = L_max(L_temp1, L_temp2);
}
coefs_shift = sub(norm_l(L_temp1), sqac_headroom_fx[N]);
L_temp = L_deposit_l(0);
FOR (i=0; i<N; i++)
{
coefs16[i] = extract_h(L_shl(L_x[i], coefs_shift));
L_temp = L_mac0(L_temp, coefs16[i], coefs16[i]);
}
if( sub(N, 1) > 0 )
{
Mpy_32_16_ss(L_temp, inv_tbl_fx[N], &L_temp, &lsb);
}
power_shift = shl(sub(coefs_shift, 16), 1);
temp_shift = norm_l(L_temp);
m = add(temp_shift, power_shift);
L_temp1 = L_add(L_shl(L_temp, temp_shift), lshr(lsb, sub(16, temp_shift)));
m = add(offset, m);
test();
IF( m < 5 && hvq_flag )
{
m = shl(m, 1);
IF( L_sub(L_temp1, 1276901417L /* 2^0.25 Q30 */) < 0 )
{
m = add(m, 2);
}
ELSE if( L_sub(L_temp1, 1805811301L /* 2^0.75 Q30 */) < 0 )
{
m = add(m, 1);
}
}
ELSE
{
if ( L_sub(L_temp1, THREN2POW /* 2^0.5 Q30 */) < 0 )
{
m = add(m, 1);
}
if ( hvq_flag )
{
m = add(m, 5); /* offset, 5 extra levels in HVQ codebook */
}
}
*k = s_max(m, 0);
i = sub(L, 1);
*k = s_min(*k, i);
return;
}
void logqnorm_2_fx(
const Word32 *env_fl, /* o, Q10 : index */
const Word16 L, /* i : codebook length */
const Word16 n_env_band, /* i : sub-vector size */
const Word16 nb_sfm, /* i : sub-vector size */
Word16 *ynrm,
Word16 *normqlg2,
const Word32 *thren /* i, Q10 : quantization thresholds */
)
{
Word16 i, j, j1, j2;
Word32 temp, power;
FOR( i=n_env_band; i < nb_sfm; i++ )
{
temp = env_fl[ sub(i,n_env_band) ];
IF ( L_sub(thren[0], temp) <= 0 )
{
*ynrm = 0;
move16();
}
ELSE IF ( L_sub(thren[sub(L,2)], temp) > 0)
{
*ynrm = sub(L, 1);
}
ELSE
{
power = temp;
move16();
j1 = 0;
move16();
j2 = sub(L, 1);
WHILE ( sub(sub(j2,j1),1) > 0 )
{
j = shr(add(j1 , j2), 1);
IF ( L_sub(power,thren[j]) >= 0 )
{
j2 = j;
move16();
}
ELSE
{
j1 = j;
move16();
}
}
*ynrm = j2;
move16();
}
*normqlg2 = dicnlg2[*ynrm];
move16();
normqlg2++;
ynrm++;
}
return;
}
/*--------------------------------------------------------------------------
* calc_norm_fx()
*
* Calculate the norms for the spectral envelope
*--------------------------------------------------------------------------*/
void calc_norm_fx(
const Word32 *L_x, /* i : Input vector. Qx */
const Word16 qx, /* i : Q value of input */
Word16 *norm, /* o : Quantization indices for norms Q0 */
Word16 *normlg, /* o : Quantized norms in log2 Q0 */
const Word16 start_band, /* i : Indice of band to start coding Q0 */
const Word16 num_bands, /* i : Number of bands Q0 */
const Word16 *band_len, /* i : Length of bands Q0 */
const Word16 *band_start /* i : Start of bands Q0 */
)
{
Word16 nrm;
Word16 band;
Word16 tmp;
set16_fx(norm, 0, start_band);
logqnorm_fx(&L_x[band_start[start_band]], qx, &nrm, 32, band_len[start_band], 0);
norm[start_band] = nrm;
move16();
normlg[start_band] = dicnlg2[nrm];
move16();
tmp = add(start_band, num_bands);
FOR (band = add(start_band, 1); band < tmp; band++)
{
logqnorm_fx(&L_x[band_start[band]], qx, &nrm, 40, band_len[band], 0);
norm[band] = nrm;
move16();
normlg[band] = dicnlg2[nrm];
move16();
}
return;
}
+47
View File
@@ -0,0 +1,47 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdio.h>
#include <assert.h>
#include "prot_fx.h"
#include "stl.h"
/**
* \brief inplace long shift right: a[] = a[] >> bits
* Logical shift right of UWord32 vector a[] by 'bits' positions.
* BASOP cycles: FLC cycles
* len = 1: 8 lena = 2: 24
* len = 2: 13 lena = 4: 34
* len = 3: 18 lena = 6: 44
* len = 4: 23 lena = 8: 54
* \param UWord32 a[]
* Input: vector of the length len
* \param Word16 bits
* Input: number of bit positions to shift right in range 1..31
* Note: 'bits' must not be 0, this would cause a shift-overflow
* \param Word16 len
* Input: length of vector a[] in units of 'UWord32'
*
* \return void
*/
void longshr(UWord32 a[], Word16 bits, Word16 len)
{
Word16 fracb_u, k;
assert ((bits > 0) && (bits < 32));
fracb_u = sub(32,bits);
len = sub(len,1);
FOR (k=0; k < len; k++)
{
a[k] = L_or(L_lshr(a[k],bits),L_lshl(a[k+1],fracb_u));
move32();
}
a[k] = L_lshr(a[k],bits);
move32();
return;
}
+219
View File
@@ -0,0 +1,219 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include "options.h" /* Compilation switches */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h"
#include "stl.h" /* required for wmc_tool */
/*--------------------------------------------------------------------------*
* fine_gain_pred()
*
* Fine gain prediction
*--------------------------------------------------------------------------*/
void fine_gain_pred_fx(
const Word16 *sfm_start, /* i : Sub band start indices */
const Word16 *sfm_end, /* i : Sub band end indices */
const Word16 *sfm_size, /* i : Sub band bandwidths */
const Word16 *i_sort, /* i : Energy sorting indices */
const Word16 *K, /* i : Number of pulses per band */
const Word16 *maxpulse, /* i : Maximum pulse per band */
const Word16 *R, /* i : Bits per sub band Q3 */
const Word16 num_sfm, /* i : Number of sub bands */
Word16 *xq, /* i/o: Quantized vector /quantized vector with finegain adj Q15*/
Word16 *y, /* i/o: Quantized vector (int) */
Word16 *fg_pred, /* o : Predicted fine gains Q12 */
const Word16 core /* i : Core */
)
{
Word16 i, band;
Word16 gp;
Word32 xx;
Word16 accuracy;
Word16 k, bw;
Word16 shift, bw_idx;
Word16 tmp, exp, exp2;
Word32 L_tmp;
UWord16 lsb;
FOR( band = 0; band < num_sfm; band++)
{
k = K[i_sort[band]];
move16();
IF( k > 0)
{
/* bw, bw_idx only used if k>0 */
bw = sfm_size[i_sort[band]];
move16(); /* allowed. 8, 16, 24,32,48,64,80,96 */
bw_idx = band_len_idx[ shr(bw,3) ];
move16(); /* bw_idx= 0: 7 */
xx = L_deposit_l(0);
shift = band_len_ener_shift[bw_idx];
FOR(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++)
{
/*xx += xq[i] * xq[i]; */
tmp = shr(xq[i], shift); /*15-shift */
xx = L_mac0(xx, tmp, tmp); /*30-2*shift */
}
IF ( xx > 0)
{
/* Normalize synthesis to RMS=1.0 */
/*gp = (float) sqrt(bw / xx); */
exp = norm_l(xx);
L_tmp = L_shl(xx, exp); /*2*(15-shift)+exp */
exp = sub(31, add(exp, sub(30, shl(shift,1))));
L_tmp = Isqrt_lc(L_tmp, &exp); /*31 - exp */
Mpy_32_16_ss(L_tmp, fine_gain_pred_sqrt_bw[bw_idx], &L_tmp, &lsb); /*31-exp+11-15=27-exp */
gp = round_fx(L_shl(L_tmp, add(1, exp))); /*27-exp+1+exp-16=12 */
test();
test();
IF (sub(core, HQ_CORE) == 0 && R != NULL && sub(R[i_sort[band]], 256) <= 0) /* 256 is 32 in Q3 */
{
/*accuracy = ((float)k/(float)bw)*maxpulse[i_sort[band]]; */
L_tmp = L_mult(k, inv_tbl_fx[bw]); /*0+15+1 */
exp2 = norm_l(L_tmp);
tmp = round_fx(L_shl(L_tmp, exp2)); /*16+exp2-16 */
L_tmp = L_mult0(maxpulse[i_sort[band]], tmp); /*0+exp2 */
exp = norm_l(L_tmp);
accuracy = round_fx(L_shl(L_tmp, exp)); /*exp2+exp-16=exp-16 */
exp = add(exp, exp2);
/*gp *= 1.0f - 0.05f / accuracy; */
tmp = div_s(13107, accuracy); /* 0.05 in Q18 */
tmp = shr(tmp, sub(34, exp)); /*15+18-exp+16-15=34-exp */
tmp = sub(32767, tmp);
tmp = s_max(27554, tmp); /* Limit attenuation to norm quantizer error, 2^-0.25 in Q15 */
gp = mult_r(tmp, gp); /*15+12+1-16=12 */
}
fg_pred[band] = gp;
move16();
}
ELSE
{
fg_pred[band] = 0;
move16();
}
}
ELSE
{
fg_pred[band] = 0;
move16();
FOR(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++)
{
y[i] = 0;
move16();
xq[i] = 0;
move16();
}
}
}
return;
}
/*--------------------------------------------------------------------------*
* get_max_pulses()
*
* Find the maximum pulse height (in unit pulses) in each band
*--------------------------------------------------------------------------*/
void get_max_pulses_fx(
const Word16 *band_start, /* i : Sub band start indices */
const Word16 *band_end, /* i : Sub band end indices */
const Word16 *k_sort, /* i : Indices for sorting by energy */
const Word16 *npulses, /* i : Pulses per sub band */
const Word16 BANDS, /* i : Number of bands */
Word16 *inp_vector, /* i/o: Encoded shape vectors (int)*/
Word16 *maxpulse /* o : Maximum pulse height per band */
)
{
Word16 i, k;
Word16 npul;
Word16 maxp;
Word16 tmp;
FOR (k = 0; k < BANDS; k++)
{
npul = npulses[k_sort[k]];
move16();
maxp = 0;
move16();
IF (npul > 0)
{
FOR (i = band_start[k_sort[k]]; i < band_end[k_sort[k]]; i++)
{
tmp = abs_s(inp_vector[i]);
if (sub(tmp, maxp) > 0)
{
maxp = tmp;
move16();
}
}
}
maxpulse[k_sort[k]] = maxp;
move16();
}
return;
}
/*--------------------------------------------------------------------------*
* fine_gain_dec()
*
* Fine gain decoder. Decodes fine gain adjustments and applies correction to
* predicted fine gains
*--------------------------------------------------------------------------*/
void fine_gain_dec_fx
(
Decoder_State_fx *st,
const Word16 *ord, /* i : Indices for energy order */
const Word16 num_sfm, /* i : Number of bands */
const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */
Word16 *fg_pred /* i/o: Predicted gains / Corrected gains */
)
{
Word16 band;
Word16 gbits;
Word16 idx, tmp1, exp1;
Word16 gain_dbq;
Word32 L_tmp;
FOR ( band = 0; band < num_sfm; band++)
{
gbits = gain_bits[ord[band]];
IF (gbits > 0)
{
IF (fg_pred[band] != 0)
{
idx = get_next_indice_fx( st, gbits );
gain_dbq = finegain_fx[gbits-1][idx];
/* Update predicted gain with quantized correction */
L_tmp = L_mult0(gain_dbq, 21771); /* 21771=0.05*log2(10) */ /* 14+17=31 */
L_tmp = L_shr(L_tmp, 15);
tmp1 = L_Extract_lc(L_tmp, &exp1);
tmp1 = abs_s(tmp1);
tmp1 = extract_l(Pow2(14, tmp1));
exp1 = sub(14, exp1);
L_tmp = L_mult0(fg_pred[band], tmp1); /*12+exp1 */
fg_pred[band] = round_fx(L_shl(L_tmp, sub(16, exp1))); /*12+exp1+16-exp1-16=12 */
}
}
}
return;
}
File diff suppressed because it is too large Load Diff
+301
View File
@@ -0,0 +1,301 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "stl.h"
#include "basop_util.h"
#include "rom_com_fx.h"
#include "cnst_fx.h"
#include "prot_fx.h"
/*---------------------------------------------------------------------*
* routine: lsf_dec_bfi()
*
* Estimate the LSFs in case of FER
* Bad frame, all active speech coders
*---------------------------------------------------------------------*/
void lsf_dec_bfi(
const Word16 codec_mode, /* i: : codec mode: MODE1 | MODE2 */
Word16*lsf, /*!< o : 14Q1*1.28 quantized ISFs */
const Word16*lsfold, /*!< i : 14Q1*1.28 past quantized ISF */
Word16*lsf_adaptive_mean, /*!< i : 14Q1*1.28 ISF adaptive mean, updated when BFI==0 */
const Word16 lsfBase[], /* i : base for differential lsf coding */
Word16*mem_MA, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */
Word16*mem_AR, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */
Word16 stab_fac, /*!< i : ISF stability factor (shifted right by 1) */
const Word16 last_coder_type, /*!< i : coding type in last good received fr. */
Word16 L_frame,
const Word16 last_good, /*!< i : last good received frame */
const Word16 nbLostCmpt, /*!< i : counter of consecutive bad frames */
Word8 plcBackgroundNoiseUpdated,
Word16 *lsf_q_cng, /* o : quantized ISFs for background noise (14Q1*1.28) */
Word16 *lsf_cng,
Word16 *old_lsf_q_cng, /* o : old quantized ISFs for background noise */
const Word16 Last_GSC_pit_band_idx,
const Word16 Opt_AMR_WB /* i : IO flag */
, const Word8 tcxonly
,const short MODE1_bwidth /* i: coded bandwidth */
)
{
Word16 i;
Word16 alpha;
Word32 tmp;
Word16 lsf_mean[M];
const Word16* pt_meansForFading;
const Word16* pt_meansForMemUpdate;
Word16 beta;
Word16 gap;
IF (sub(codec_mode,MODE1) == 0)
{
pt_meansForMemUpdate = lsf_mean;
/* Update inital guess to something stable, with proper sampling frequency and format (ISF/LSF)*/
IF ( Opt_AMR_WB)
{
pt_meansForFading = Mean_isf_wb;
}
ELSE
{
/* 12.8kHz ACELP sampling */
IF( sub(L_frame,L_FRAME) == 0 )
{
pt_meansForFading = GEWB_Ave_fx;
if (sub(MODE1_bwidth,NB)==0)
{
pt_meansForFading = GENB_Ave_fx;
}
}
/* 16kHz ACELP sampling */
ELSE
{
pt_meansForFading = GEWB2_Ave_fx;
}
}
}
ELSE
{
pt_meansForFading = pt_meansForMemUpdate = lsfBase;
test();
if (lsf_cng != NULL && plcBackgroundNoiseUpdated)
{
pt_meansForFading = lsf_cng;
}
}
IF( sub(nbLostCmpt, 3) <= 0 )
{
test();
test();
IF( (sub(last_coder_type, UNVOICED) == 0) ) /* Clear unvoiced last good frame */
{
move16();
alpha = _ALPHA_UU_FX;
}
ELSE IF( sub(last_coder_type,AUDIO) == 0 || sub(last_good,INACTIVE_CLAS) == 0 )
{
alpha = 32604/*0.995f Q15*/;
move16();
test();
if( Last_GSC_pit_band_idx > 0 && sub(nbLostCmpt, 1) > 0 )
{
alpha = 26214/*0.8f Q15*/;
move16();
}
}
ELSE IF( sub(last_good,UNVOICED_CLAS) == 0 )
{
IF( sub(nbLostCmpt,1) <= 0 )
{
/* If stable, do not flatten the spectrum in the 1st erased frame */
alpha = add(mult(stab_fac, 32768 - _ALPHA_U_FX_X_2), _ALPHA_U_FX_X_2);
}
ELSE IF(sub(nbLostCmpt,2) == 0)
{
alpha = sub(_ALPHA_U_FX_X_2,shr(_ALPHA_U_FX,1)); /* 0.6 */
}
ELSE
{
alpha = _ALPHA_U_FX;
move16(); /* go rapidly to CNG spectrum */
}
}
ELSE IF( sub(last_good ,UNVOICED_TRANSITION) == 0 )
{
alpha = _ALPHA_UT_FX;
move16();
}
ELSE IF( (sub(last_good,VOICED_CLAS) == 0) || (sub(last_good,ONSET) == 0) )
{
/* clearly voiced - mild convergence to the CNG spectrum for the first 3 erased frames */
move16();
alpha = _ALPHA_V_FX;
}
ELSE IF( sub(last_good ,SIN_ONSET) == 0 )
{
alpha = _ALPHA_S_FX;
move16();
}
ELSE
{
alpha = _ALPHA_VT_FX; /* rapid convergence to the CNG spectrum (long erasure, ONSETS) */
}
}
ELSE
{
Word16 exp = 15;
alpha = Inv16(nbLostCmpt, &exp); /*1.f/bfi_cnt;*/
alpha = shl(alpha,exp);
}
IF(sub(codec_mode,MODE1) == 0)
{
beta = BETA_FEC_FX;
move16();
}
ELSE
{
beta = 8192/*0.25f Q15*/;
move16();
if (plcBackgroundNoiseUpdated)
{
beta = 0/*0.f Q15*/;
move16();
}
}
FOR (i=0; i<M; i++)
{
lsf_mean[i] = mac_r(L_mult(beta,pt_meansForFading[i]), sub(32767/*1.0F Q15*/,beta), lsf_adaptive_mean[i]);
move16();
lsf[i] = mac_r(L_mult(alpha, lsfold[i]), sub(32767/*1.0F Q15*/, alpha), lsf_mean[i]);
move16();
IF(lsf_q_cng!=NULL)
{
lsf_q_cng[i] = mac_r(L_mult(s_max(alpha,26214/*0.8f Q15*/),old_lsf_q_cng[i]), sub(32767/*1.0f Q15*/, s_max(alpha,26214/*0.8f Q15*/)), pt_meansForFading[i]);
move16();
}
}
/* check LSF stability through LSF ordering */
IF ( Opt_AMR_WB )
{
reorder_isf_fx( lsf, ISF_GAP_FX, M, Fs_2 );
}
ELSE
{
IF( sub(L_frame,L_FRAME) == 0 )
{
IF(sub(codec_mode, MODE1) == 0)
{
reorder_lsf_fx(lsf, MODE1_LSF_GAP_FX, M, INT_FS_FX); /*arg1&2: 14Q1*1.18*/
}
ELSE
{
reorder_lsf_fx(lsf, LSF_GAP_FX, M, INT_FS_FX); /*arg1&2: 14Q1*1.18*/
}
IF(lsf_q_cng!=NULL)
{
reorder_lsf_fx(lsf_q_cng, LSF_GAP_FX, M, INT_FS_FX);
}
}
ELSE IF ( tcxonly != 0 )
{
IF ( sub(L_frame,320) == 0 )
{
gap = 143;
}
ELSE IF ( sub(L_frame,512) == 0 )
{
gap = 90;
}
ELSE IF ( sub(L_frame,640) == 0 )
{
gap = 72;
}
ELSE
{
gap = 48;
}
reorder_lsf_fx(lsf, gap, M, INT_FS_FX);
}
ELSE
{
reorder_lsf_fx(lsf, MODE1_LSF_GAP_FX, M, i_mult(L_frame, 50)); /*arg1&2: 14Q1*1.18*/
IF(lsf_q_cng!=NULL)
{
reorder_lsf_fx(lsf_q_cng, LSF_GAP_FX, M, INT_FS_16k_FX);
}
}
}
/* update the AR memory to be used in the next frame */
{
Copy(lsf,mem_AR,M);
}
/* update the MA memory to be used in the next frame */
FOR(i=0; i<M; i++)
{
/*factor 0x4000 means 0.5. Together with /2 in mem_MA-assignment,
this results in an attenuation of the MA Q memory */
tmp = L_msu(L_mult(lsf[i],0x4000),pt_meansForMemUpdate[i],0x4000);
/* Update with quantized prediction error for MA model */
mem_MA[i] = msu_r(tmp, MU_MA_FX/2,mem_MA[i]);
move16();
}
return;
}
Word16 const * PlcGetLsfBase (Word16 const lpcQuantization,
Word16 const narrowBand,
Word32 const sr_core)
{
/* Not correct BW */
IF (lpcQuantization==0)
{
/* high rates, return value is never used; the correct value changes
dynamically and is not available during PLC; therefore, the setting
is kept as before (without the define PLC_FIX_XSF_HANDLING); the
correct value would be isf[m] as returned by lpc_unquantize()
during normal decoding */
IF(L_sub(sr_core,32000)==0)
{
return means_swb_cleanspeech_lsf32k0;
}
ELSE IF(L_sub(sr_core,25600)==0)
{
return means_swb_cleanspeech_lsf25k6;
}
ELSE
{
return means_wb_cleanspeech_lsf16k0;
}
}
/* lpcQuntization == 1 is left */
IF (L_sub(sr_core,16000)==0)
{
return GEWB2_Ave_fx;
}
/* sr_core == 12.8k is left */
IF (narrowBand == 0)
{
return GEWB_Ave_fx;
}
/* narrowBand == 1 is left */
return GENB_Ave_fx;
}
+159
View File
@@ -0,0 +1,159 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include <assert.h>
#include "cnst_fx.h"
#include "rom_com_fx.h"
#include "prot_fx.h"
#include "stl.h"
#include "basop_util.h"
#include "prot_fx.h"
#include "options.h"
#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;}
extern const Word16 tbl_mid_gen_wb_5b_fx[];
extern const Word16 tbl_mid_unv_wb_5b_fx[];
void midlsf_dec(
const Word16 qlsf0[], /* i: quantized lsf coefficients (3Q12) */
const Word16 qlsf1[], /* i: quantized lsf coefficients (3Q12) */
Word16 idx, /* i: codebook index */
Word16 qlsf[], /* o: decoded lsf coefficients (3Q12) */
Word16 coder_type,
Word16 *mid_lsf_int,
Word16 prev_bfi,
Word16 safety_net)
{
const Word16 *ratio=NULL;
Word16 j;
Word32 L_tmp;
Word16 bad_spacing = 0;
move16();
/* Select codebook */
IF ( sub(coder_type, UNVOICED) == 0 )
{
ratio = tbl_mid_unv_wb_5b_fx;
}
ELSE
{
ratio = tbl_mid_gen_wb_5b_fx;
}
FOR (j=0; j<M; j++)
{
L_tmp = L_mult(sub(0x2000, ratio[idx*M+j]), qlsf0[j]); /*Q(x2.56+13+1)->Q(x2.56+14)*/
L_tmp = L_mac(L_tmp, ratio[idx*M+j], qlsf1[j]); /*Q(x2.56+14)*/
qlsf[j] = round_fx(L_shl(L_tmp,2)); /*Q(x2.56)*/
}
IF(mid_lsf_int != NULL) /*at the decoder*/
{
/* check for incorrect LSF ordering */
IF ( sub(*mid_lsf_int, 1) == 0 )
{
FOR (j=1; j<M; j++)
{
IF ( sub(qlsf[j] , qlsf[j-1]) < 0 )
{
bad_spacing = 1;
move16();
BREAK;
}
}
}
/* Redo mid-LSF interpolation with 0.4 in case of LSF instability */
test();
test();
IF( prev_bfi || ( sub(*mid_lsf_int, 1) == 0 && bad_spacing ) )
{
FOR (j=0; j<M; j++)
{
/* redo mid-LSF interpolation with 0.4 */
qlsf[j] = add(mult_r(13107, qlsf0[j]), mult_r(19661, qlsf1[j])); /* Q15 +x2.56 -Q15 13107 = 0.4(Q15), 19661 = 0.6 (Q15)*/ move16();
/* ensure correct ordering of LSF indices */
test();
test();
IF ( j > 0 && sub(j, M) <0 && sub(qlsf[j], add( qlsf[j-1], LSF_GAP_MID_FX))<0 )
{
qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX);
move16();
}
}
}
ELSE
{
/* otherwise, use regular LSF spacing and ordering as in the encoder */
FOR (j=0; j<M; j++)
{
test();
test();
IF ( j > 0 && sub(j, M) < 0 && sub(qlsf[j], add( qlsf[j-1],LSF_GAP_MID_FX))<0 )
{
qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX);
move16();
}
}
}
if ( prev_bfi )
{
/* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */
*mid_lsf_int = 1;
move16();
}
if ( safety_net )
{
/* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */
*mid_lsf_int = 0;
move16();
}
}
ELSE
{
/* use regular LSF spacing */
FOR (j=0; j<M; j++)
{
test();
test();
IF ( j > 0 && sub(j, M) <0 && sub(qlsf[j], add(qlsf[j-1], LSF_GAP_MID_FX))<0 )
{
qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX);
move16();
}
}
}
return;
}
Word16 lsf_ind_is_active(
const Word16 lsf_q_ind[],
const Word16 means[],
Word16 narrowband,
Word16 cdk
)
{
Word16 lsf[2], min_distance;
lsf[0] = add(lsf_q_ind[0], means[0]);
move16();
lsf[1] = add(lsf_q_ind[1], means[1]);
move16();
min_distance = lsf[0];
move16();
min_distance = s_min(min_distance, sub(lsf[1], lsf[0]));
assert(narrowband == 0 || narrowband == 1);
assert(cdk == 0 || cdk == 1);
return sub(min_distance, min_distance_thr[narrowband][cdk]) < 0;
}
File diff suppressed because it is too large Load Diff
+858
View File
@@ -0,0 +1,858 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
/* The conversion modes. */
#define DOWNCONV 0
#define UPCONV 1
#define NC (M/2)
/*-------------------------------------------------------------------*
* Local functions
*-------------------------------------------------------------------*/
static void powerspect_fx(
const Word16 x[], /* i: Q15 Grid points x[0:m-1] */
Word16 N, /* i: Number of grid points */
Word32 R[], /* i: Q20 Coefficients of R(x) in R[0:NC] */
Word32 S[], /* i: Q20 Coefficients of S(x) in S[0:NC] */
Word32 G[], /* o: Q15 Power spectrum G[0:N] */
Word16 mode /* i: Flag for up or down conversion */
);
static void spectautocorr_fx(
const Word16 x[], /* i: Grid points x[0:m-1] */
const Word16 N, /* i: Number of grid points */
const Word32 G[], /* i: Power spectrum G[0:N-1] */
Word16 rh[], /* o: Autocorrelation r[0:M] */
Word16 rl[] /* o: Autocorrelation r[0:M] */
);
static Word32 b_inv_sq(
const Word32 in32, /* i : Input not normalized to inverse */
const Word16 exp_in /* I : input current exponent */
);
static Word32 inv_pow(
const Word32 re,
const Word32 se,
const Word16 x
);
static void zeros2poly_fx( Word16 x[], Word32 R[], Word32 S[] );
static void polydecomp_fx(
Word16 A[], /* i: Q12 linear prediction coefficients */
Word32 P[], /* o: Q22 coefficients of R(x) */
Word32 Q[] /* o: Q22 coefficients of S(x) */
);
static void cheb2poly_fx(
Word32 L_P[] /* i/o Q22: The coefficients of C(x) and P(x) */
);
/*---------------------------------------------------------------------*
* lsp_convert_poly()
*
* Converts the LP filter estimated at 16.0 kHz sampling rate down
* 12.8 kHz frequency scale or alternatively from 12.8 kHz up to
* 16.0 kHz. The former is called down conversation and latter up
* conversion. The resulting LP filter is characterized with its
* line spectrum pairs. The original Lp filter can be either in
* its immittance, used for the AMR-WB IO mode, or line spectrum
* pair representation.
*
* The conversion is based the autocorrelation computed from the
* power spectrum of the LP filter that is truncated or extrapolated
* to the desired frequency scale.
*---------------------------------------------------------------------*/
Word16 lsp_convert_poly_fx(
Word16 w[], /* i/o: LSP or ISP parameters */
const Word16 L_frame, /* i : flag for up or down conversion */
const Word16 Opt_AMRWB /* i : flag for the AMR-WB IO mode */
)
{
const Word16 N50 = GRID50_POINTS;
const Word16 N40 = GRID40_POINTS;
Word16 flag;
Word32 G[GRID50_POINTS];
Word16 i;
Word16 A[M+1];
Word32 R[NC+1], S[NC+1];
Word32 epsP[M+1];
Word16 rh[M+1], rl[M+1];
Word16 oldA[M+3];
/*---------------------------------------------------------------------*
* Because AMR-WB IO mode uses immittance spectrum frequency representation
* instead of line spectrum frequency representation, the input
* parameters do not give the zeros of the polynomials R(x) and S(x).
* Hence R(x) and S(x) are formed via the polynomial A(z) of the linear
* prediction filter.
*---------------------------------------------------------------------*/
IF( Opt_AMRWB )
{
E_LPC_f_isp_a_conversion( w, oldA, M );
polydecomp_fx( oldA, R, S );
}
/*---------------------------------------------------------------------*
* Form the polynomials R(x) and S(x) from their zeros that are the
* line spectrum pairs of A(z). The polynomial coefficients can be
* scaled for convenience, because scaling will not affect the
* resulting LP coefficients. Scaling by 128 gives the correct offset
* to the power spectrum for n = 16.
*---------------------------------------------------------------------*/
ELSE
{
E_LPC_f_lsp_a_conversion( w, oldA, M );
zeros2poly_fx(w, R, S);
}
/*---------------------------------------------------------------------*
* Conversion from 16.0 kHz down to 12.8 kHz. The power spectrum
* needs to be computed only up to 6.4 kHz, because the upper band
* is omitted.
*---------------------------------------------------------------------*/
IF (sub(L_frame,L_FRAME) == 0)
{
powerspect_fx(grid50_fx, N50, R, S, G, DOWNCONV);
spectautocorr_fx(grid40_fx, N40, G, rh, rl);
}
/*---------------------------------------------------------------------*
* Conversion from 12.8 kHz up to 16.0 kHz.
* Compute the power spectrum of the LP filter, extrapolate the
* power spectrum from 6.4 kHz to 8.0 kHz, and compute auto-
* correlation on this power spectrum.
*---------------------------------------------------------------------*/
ELSE
{
powerspect_fx(grid40_fx, N40, R, S, G, UPCONV);
FOR (i = N40; i < N50; i++)
{
G[i] = G[N40-1];
move32();
}
spectautocorr_fx(grid50_fx, N50, G, rh, rl);
}
/*---------------------------------------------------------------------*
* Compute the linear prediction coefficients from the autocorrelation
* and convert to line spectrum pairs.
*---------------------------------------------------------------------*/
flag=E_LPC_lev_dur(rh, rl, A, epsP, M, oldA);
E_LPC_a_lsp_conversion(A, w, stable_LSP_fx, M );
return(flag);
}
/*---------------------------------------------------------------------*
* powerspect()
*
* Computes the power spectrum G(w) = 1/|A(w)|^2 at N points on
* the real axis x = cos w by utilizing the line spectrum frequency
* decomposition
*
* A(z) = (P(z) + Q(z))/2,
*
* where assuming A(z) of an even degree n,
*
* P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
* Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1).
*
* The zeros of these polynomials give the line spectrum frequencies
* of A(z). It can be shown that for an even n,
*
* |A(x)|^2 = 2 (1 + x) R(x)^2 + 2 (1 - x) S(x)^2,
*
* where x = cos w, and R(x) and S(x) are the direct polynomials
* resulting from the Chebyshev series representation of P(z)
* and Q(z).
*
* This routine assumes the grid X = 1, x[0], x[1], .., x[m-1],
* -, ..., -x[1], -x[0], -1 such that x[i] = cos((i+1)*pi/N) for
* evaluating the power spectrum. Only m = (N-1)/2 - 1 grid points
* need to be stored, because cos(0) and cos(pi/2) are trivial,
* and the points above pi/2 are obtained readily using the symmetry
* of cosine.
*
* The power spectrum can be scaled as a*G[], where a is chosen
* for convenience. This is because the scaling has no impact on
* the LP coefficients to be determined based on the power spectrum.
*---------------------------------------------------------------------*/
void powerspect_fx(
const Word16 x[], /* i: Q15 Grid points x[0:m-1] */
Word16 N, /* i: Number of grid points */
Word32 R[], /* i: Q20 Coefficients of R(x) in R[0:NC] */
Word32 S[], /* i: Q20 Coefficients of S(x) in S[0:NC] */
Word32 G[], /* o: Q15 Power spectrum G[0:N] */
Word16 mode /* i: Flag for up or down conversion */
)
{
Word32 s0, se, so, r0, re, ro;
Word16 i, j;
Word16 iuni, imid;
Word32 L_tmp;
Word16 x2;
Word32 mh;
UWord16 ml;
/*---------------------------------------------------------------------*
* Down conversion yields iuni unique grid points that do not have
* symmetric counterparts above x = cos(pi/2) = 0.
* Set the mid point of the frequency grid.
*---------------------------------------------------------------------*/
IF (mode == DOWNCONV)
{
iuni = (GRID50_POINTS - 1)/5 - 1;
move16();
imid = (GRID50_POINTS - 1)/2;
move16();
}
/*---------------------------------------------------------------------*
* Power spectrum x = cos(pi) = -1 that is not needed in down
* conversion. Set the mid point of the frequency grid.
*---------------------------------------------------------------------*/
ELSE
{
iuni = 0;
move16();
imid = (GRID40_POINTS - 1)/2;
move16();
G[N-1] = S[0];
move32();
FOR (j = 1; j <= NC; j++)
{
G[N-1] = L_sub(S[j], G[N-1]);
move32();
}
G[N-1] = b_inv_sq(G[N-1], 19);
move32();
}
/*---------------------------------------------------------------------*
* Power spectrum x = cos(0) = 1.
*---------------------------------------------------------------------*/
G[0] = R[0];
move32();
FOR (j = 1; j <= NC; j++)
{
G[0] = L_add(R[j], G[0]);
move32();
}
G[0] = b_inv_sq(L_max(G[0],1), 19);
move32();
/*---------------------------------------------------------------------*
* Power spectrum at x = cos(pi/2) = 0.
*---------------------------------------------------------------------*/
G[imid] = inv_pow(R[NC], S[NC], 0);
move32();
/*---------------------------------------------------------------------*
* Power spectrum at unique points that do not have symmetric
* counterparts at x > cos(pi/2) = 0.
*---------------------------------------------------------------------*/
FOR (i = 1; i <= iuni; i++)
{
Mpy_32_16_ss(R[0], x[i-1], &mh, &ml);
r0 = L_add(R[1], mh);
Mpy_32_16_ss(S[0], x[i-1], &mh, &ml);
s0 = L_add(S[1], mh);
FOR (j = 2; j <= NC; j++)
{
Mpy_32_16_ss(r0, x[i-1], &mh, &ml);
r0 = L_add(R[j], mh);
Mpy_32_16_ss(s0, x[i-1], &mh, &ml);
s0 = L_add(S[j], mh);
}
G[i] = inv_pow(r0, s0, x[i-1]);
move32();
}
/*---------------------------------------------------------------------*
* Power spectrum at points other than x = -1, 0, and 1 and unique
* points is computed using the anti-symmetry of the grid relative
* to the midpoint x = 0 in order to reduce looping.
*---------------------------------------------------------------------*/
FOR ( ; i < imid; i++)
{
x2 = mult_r(x[i-1], x[i-1]);
Mpy_32_16_ss(R[0], x2, &mh, &ml);
re = L_add(R[2], mh);
Mpy_32_16_ss(R[1], x2, &mh, &ml);
ro = L_add(R[3], mh);
Mpy_32_16_ss(S[0], x2, &mh, &ml);
se = L_add(S[2], mh);
Mpy_32_16_ss(S[1], x2, &mh, &ml);
so = L_add(S[3], mh);
FOR (j = 4; j < NC; j+=2)
{
Mpy_32_16_ss(re, x2, &mh, &ml);
re = L_add(R[j], mh);
Mpy_32_16_ss(ro, x2, &mh, &ml);
ro = L_add(R[j+1], mh);
Mpy_32_16_ss(se, x2, &mh, &ml);
se = L_add(S[j], mh);
Mpy_32_16_ss(so, x2, &mh, &ml);
so = L_add(S[j+1], mh);
}
Mpy_32_16_ss(re, x2, &mh, &ml);
L_tmp = L_add(R[j], mh);
Mpy_32_16_ss(ro, x[i-1], &mh, &ml);
re = L_add(L_tmp, mh);
ro = L_sub(L_tmp, mh);
Mpy_32_16_ss(se, x2, &mh, &ml);
L_tmp = L_add(S[j], mh);
Mpy_32_16_ss(so, x[i-1], &mh, &ml);
se = L_add(L_tmp, mh);
so = L_sub(L_tmp, mh);
G[i] = inv_pow(re, se, x[i-1]);
move32();
G[N-i-1] = inv_pow(so, ro, x[i-1]);
move32();
}
return;
}
static Word32 b_inv_sq(
const Word32 in32, /* i : Input not normalized to inverse */
const Word16 exp_in /* i : input current exponent */
)
{
Word16 m_den, exp_den;
Word16 div_out;
Word32 Ltmp;
exp_den = norm_l(in32);
m_den = extract_h(L_shl(in32, exp_den));
exp_den = add(sub(30,exp_den),sub(16,exp_in));
m_den = mult_r(m_den, m_den);
exp_den = shl(exp_den,1);
div_out = div_s(8192,m_den);
Ltmp = L_shl(div_out, add(sub(30-13, exp_den),15)); /*Q15*/
return Ltmp;
}
static Word32 inv_pow(
const Word32 re,
const Word32 se,
const Word16 x
)
{
Word16 exp1, exp2;
Word16 tmp;
Word32 L_tmp;
Word32 mh;
UWord16 ml;
Word32 r0, s0;
IF(re==0)
{
exp1 = 30;
move16();
r0 = L_deposit_l(0);
}
ELSE
{
exp1 = norm_l(re);
tmp = extract_h(L_shl(re, exp1));
L_tmp = L_shr(L_mult(tmp, tmp), 1);
Mpy_32_16_ss(L_tmp, x, &mh, &ml);
r0 = L_add(L_tmp, mh);
}
IF(se==0)
{
exp2 = 30;
move16();
s0 = L_deposit_l(0);
}
ELSE
{
exp2 = norm_l(se);
tmp = extract_h(L_shl(se, exp2));
L_tmp = L_shr(L_mult(tmp, tmp), 1);
Mpy_32_16_ss(L_tmp, x, &mh, &ml);
s0 = L_sub(L_tmp, mh);
}
IF(exp1 > exp2)
{
exp1 = shl(sub(exp1, exp2), 1);
r0 = L_shr(r0, exp1);
exp2 = add(add(exp2, exp2), 8);
}
ELSE
{
exp2 = shl(sub(exp2, exp1), 1);
s0 = L_shr(s0, exp2);
exp2 = add(add(exp1, exp1), 8);
}
r0 = L_add(r0, s0);
exp1 = norm_l(r0);
L_tmp = L_shl(r0, exp1);
tmp = extract_h(L_tmp);
IF(tmp==0)
{
return MAX_32;
}
tmp = div_s((Word16)((1<<14)-1), tmp);
exp1 = add(exp1, exp2);
L_tmp = L_shr(tmp, sub(31, exp1)); /* result in Q15 */
return(L_tmp);
}
/*---------------------------------------------------------------------*
* spectautocorr()
*
* Computes the autocorrelation r[j] for j = 0, 1, ..., M from
* the power spectrum P(w) by using rectangle rule to approximate
* the integral
*
* 1 pi
* r[j] = --- I P(w) cos(j*w) dw.
* 2*pi -pi
*
* It is sufficient to evaluate the integrand only from w = 0 to
* w = pi due to the symmetry P(-w) = P(w). We can further
* employ the relation
*
* cos(j*(pi - w)) = (-1)^j cos(j*w)
*
* to use symmetries relative to w = pi/2.
*
* When applying the rectangle rule, it is useful to separate w = 0,
* w = pi/2, and w = pi. By using a frequency grid of N points, we
* can express the rectangle rule as
*
* r[j] = G[0] + 2*a*G[(N-1)/2] + b*G[N-1]
*
* M
* + 2 sum (G[i] - G[N-i-1]) cos(j*x[i])
* i=1
*
* where G[i] is the power spectrum at the grid point cos(i*pi/N)
* and M = (N-1)/2 - 1 is the number of the grid points in the
* interval(0, pi/2).
*
* The coefficients
*
* b = (-1)^j
* a = (1 + (-1)^(j+1))(-1)^floor(j/2)
*
* follow from the properties of cosine. The computation further
* uses the recursion
*
* cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w)
*
* Note that the autocorrelation can be scaled for convenience,
* because this scaling has no impact on the LP coefficients to be
* calculated from the autocorrelation. The expression of r[j] thus
* omits the division by N.
*
* See the powerspect function on the definition of the grid.
*
* References
* J. Makhoul, "Spectral linear prediction: properties and
* applications," IEEE Trans. on Acoustics, Speech and Signal
* Processing, Vol. 23, No. 3, pp.283-296, June 1975
*---------------------------------------------------------------------*/
static void spectautocorr_fx(
const Word16 x[], /* i: Grid points x[0:m-1] */
const Word16 N, /* i: Number of grid points */
const Word32 G[], /* i: Power spectrum G[0:N-1] */
Word16 rh[], /* o: Autocorrelation r[0:M] */
Word16 rl[] /* o: Autocorrelation r[0:M] */
)
{
Word16 c[M+1]; /* c[j] = cos(j*w) */
Word32 gp, gn;
Word16 i, j;
Word16 imid;
Word32 mh;
UWord16 ml;
Word32 r[M+1];
Word16 exp0;
/*---------------------------------------------------------------------*
* The mid point of the cosine table x of m entries assuming an odd m.
* Only the entries x[0] = cos(pi/m), x[1] = cos(2*pi/m), ...,
* x[imid-1] = cos((imid-1)*pi/m) need to be stored due to trivial
* cos(0), cos(pi/2), cos(pi), and symmetry relative to pi/2.
* Here m = 51.
*---------------------------------------------------------------------*/
imid = (N - 1)/2;
move16();
/*---------------------------------------------------------------------*
* Autocorrelation r[j] at zero lag j = 0 for the upper half of the
* unit circle, but excluding the points x = cos(0) and x = cos(pi).
*---------------------------------------------------------------------*/
r[0] = G[1];
move32();
FOR (i = 2; i < N-1; i++)
{
r[0] = L_add(r[0], G[i]);
move32();
}
/*---------------------------------------------------------------------*
* Initialize the autocorrelation r[j] at lags greater than zero
* by adding the midpoint x = cos(pi/2) = 0.
*---------------------------------------------------------------------*/
r[1] = L_deposit_l(0);
r[2] = -G[imid];
move32();
FOR (i = 3; i < M; i+=2)
{
r[i] = L_deposit_l(0);
r[i+1] = -r[i-1];
move32();
}
/*---------------------------------------------------------------------*
* Autocorrelation r[j] at lags j = 1, 2, ..., M. The computation
* employes the relation cos(j*(pi - w)) = (-1)^j cos(j*w) and
* cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w) for obtaining
* the cosine c[j] = cos(j*w).
*---------------------------------------------------------------------*/
c[0] = (Word16)32767;
move16(); /* 1.0 in Q15 */
FOR (i = 1; i < imid; i++)
{
gp = L_add(G[i], G[N-i-1]);
gn = L_sub(G[i], G[N-i-1]);
/*r[1] = L_mac(r[1], x[i-1], gn);*/
Mpy_32_16_ss(gn, x[i-1], &mh, &ml);
r[1] = L_add(r[1], mh);
move32();
c[1] = x[i-1];
move16();
FOR (j = 2; j < M; j+=2)
{
c[j] = mult_r(c[j-1], x[i-1]);
move16();
c[j] = add(c[j], sub(c[j], c[j-2]));
move16();
/*r[j] = L_mac(r[j], c[j], gp);*/
Mpy_32_16_ss(gp, c[j], &mh, &ml);
r[j] = L_add(r[j], mh);
move32();
c[j+1] = mult_r(c[j], x[i-1]);
move16();
c[j+1] = add(c[j+1], sub(c[j+1], c[j-1]));
move16();
/*r[j+1] = L_mac(r[j+1], c[j+1], gn);*/
Mpy_32_16_ss(gn, c[j+1], &mh, &ml);
r[j+1] = L_add(r[j+1], mh);
move32();
}
c[j] = mult_r(c[j-1], x[i-1]);
move16();
c[j] = add(c[j], sub(c[j], c[j-2]));
move16();
Mpy_32_16_ss(gp, c[j], &mh, &ml);
r[j] = L_add(r[j], mh);
move32();
}
/*---------------------------------------------------------------------*
* Add the endpoints x = cos(0) = 1 and x = cos(pi) = -1 as
* well as the lower half of the unit circle.
*---------------------------------------------------------------------*/
gp = L_shr(L_add(G[0], G[N-1]), 1);
gn = L_shr(L_sub(G[0], G[N-1]), 1);
r[0]= L_add(r[0], gp);
move32();
exp0 = norm_l(r[0]);
L_Extract(L_shl(r[0], exp0), &rh[0], &rl[0]);
FOR (j = 1; j < M; j+=2)
{
L_Extract(L_shl(L_add(r[j], gn), exp0), &rh[j], &rl[j]);
L_Extract(L_shl(L_add(r[j+1], gp), exp0), &rh[j+1], &rl[j+1]);
}
return;
}
/*---------------------------------------------------------------------*
* zeros2poly()
*
* Computes the coefficients of the polynomials
*
* R(x) = prod (x - x[i]),
* i = 0,2,4,...
*
* S(x) = prod (x - x[i]),
* i = 1,3,5,...
*
* when their zeros x[i] are given for i = 0, 1, ..., n-1. The
* routine assumes n = 1 or even n greater than or equal to 4.
*
* The polynomial coefficients are returned in R[0:n/2-1] and
* S[0:n/2-1]. The leading coefficients are in R[0] and S[0].
*---------------------------------------------------------------------*/
static void zeros2poly_fx(
Word16 x[], /* i: Q15 Zeros of R(x) and S(x) */
Word32 R[], /* o: Q22 Coefficients of R(x) */
Word32 S[] /* o: Q22 Coefficients of S(x) */
)
{
Word16 xr, xs;
Word16 i, j;
Word32 mh;
UWord16 ml;
R[0] = (1<<27)-1;
move32();
S[0] = (1<<27)-1;
move32();
R[1] = L_msu(0, x[0], 1<<11);
move32();
S[1] = L_msu(0, x[1], 1<<11);
move32();
FOR (i = 2; i <= NC; i++)
{
xr = negate(x[2*i-2]);
xs = negate(x[2*i-1]);
Mpy_32_16_ss(R[i-1], xr, &R[i], &ml);
Mpy_32_16_ss(S[i-1], xs, &S[i], &ml);
FOR (j = i-1; j > 0; j--)
{
Mpy_32_16_ss(R[j-1], xr, &mh, &ml);
R[j] = L_add(R[j], mh);
Mpy_32_16_ss(S[j-1], xs, &mh, &ml);
S[j] = L_add(S[j], mh);
}
}
return;
}
/*---------------------------------------------------------------------*
* polydecomp()
*
* Computes the coefficients of the symmetric and antisymmetric
* polynomials P(z) and Q(z) that define the line spectrum pair
* decomposition of a given polynomial A(z) of order n. For even n,
*
* P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
* Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1),
*
* These polynomials are then expressed in their direct form,
* respectively, R(x) and S(x), on the real axis x = cos w using
* explicit Chebyshev polynomials of the first kind.
*
* The coefficients of the polynomials R(x) and S(x) are returned
* in R[0:n/2] and S[0:n/2] for the given linear prediction
* coefficients A[0:n/2]. Note that R(x) and S(x) are formed in
* place such that P(z) is stored in the same array than R(x),
* and Q(z) is stored in the same array than S(x).
*
* The routines assumes n = 16.
*---------------------------------------------------------------------*/
static void polydecomp_fx(
Word16 A[], /* i: Q12 linear prediction coefficients */
Word32 R[], /* o: Q20 coefficients of R(x) */
Word32 S[] /* o: Q20 coefficients of S(x) */
)
{
Word16 scale;
Word16 i;
Word32 Ltmp1, Ltmp2;
scale = shl((1<<5), norm_s(A[0]));
R[0] = (1<<20)-1;
move32(); /* Q20 */
S[0] = (1<<20)-1;
move32();
FOR(i=0; i<NC; i++)
{
Ltmp1 = L_mult(A[i+1], scale);
Ltmp2 = L_msu(Ltmp1, A[M-i], scale);
Ltmp1 = L_mac(Ltmp1, A[M-i], scale);
R[i+1] = L_sub(Ltmp1, R[i]);
move32();
S[i+1] = L_add(Ltmp2, S[i]);
move32();
}
cheb2poly_fx(R);
cheb2poly_fx(S);
return;
}
/*---------------------------------------------------------------------*
* cheb2poly_fx()
*
* Computes the coefficients of the explicit Chebyshev polynomial
* P(x) = P[0]*x^n + P[1]*x^(n-1) + ... + P[n] given the coefficients
* of the series
*
* C(x) = C[0]*T_n(x) + C[1]*T_n-1(x) + ... + C[n]*T_0(x)
*
* where T_n(x) is the nth Chebyshev polynomial of the first kind.
* This implementation assumes C[0] = 1. Only value n = 8 is
* supported.
*
* The conversion from C(x) to P(x) is done in place such that the
* coefficients of C(x) are given in P[0:8] and those of P(x) are
* returned in the same array.
*---------------------------------------------------------------------*/
static void cheb2poly_fx(
Word32 L_P[] /* i/o Q20: The coefficients of C(x) and P(x) */
)
{
Word32 L_C[NC+1], L_tmp;
Word16 i;
FOR(i=1; i<=NC; i++)
{
L_C[i] = L_P[i];
move32();
}
L_P[0] = (1<<27)-1;
move32();
L_P[1] = L_shl(L_C[1], 6);
move32(); /* 64.0*C[1] */
L_P[8] = L_shl(L_C[1], 3);
move32(); /* 8.0*C[1] */
L_P[5] = L_sub(L_P[1], L_P[8]);
move32(); /* 56.0*C[1] */
L_P[2] = L_shl(L_C[3], 2);
move32();
L_tmp = L_add(L_C[3], L_P[2]); /* 5.0*C[3] */
L_P[7] = L_sub(L_tmp, L_sub(L_P[8], L_C[1]));
move32(); /* -7.0*C[1] */
L_P[8] = L_shl(L_C[3], 4);
move32(); /* 16.0*C[3] */
L_P[3] = L_sub(L_P[8], L_shl(L_P[5], 1));
move32(); /*-112.0*C[1] */
L_P[5] = L_sub(L_P[5], L_add(L_P[8], L_P[2]));
move32(); /* -20.0*C[3] */
L_P[2] = L_shl(L_C[5], 2);
move32();
L_P[5] = L_add(L_P[5], L_P[2]);
move32(); /* 4.0*C[5] */
L_tmp = L_sub(L_P[7], L_sub(L_P[2], L_C[5])); /* -3.0*C[5] */
L_P[7] = L_add(L_tmp, L_C[7]);
move32(); /* C[7] */
L_P[6] = L_shl(L_C[2], 4);
move32();
L_tmp = L_sub((160<<20), L_P[6]);
L_P[4] = L_sub(L_tmp, L_shl(L_C[2], 5));
move32(); /* -48.0*C[2] */
L_tmp = L_add(L_P[6], L_shl(L_C[2], 1)); /* 18.0*C[2] */
L_P[6] = L_sub(L_tmp, (32<<20));
move32();
L_P[8] = L_shl(L_C[4], 3);
move32();
L_P[4] = L_add(L_P[4], L_P[8]);
move32(); /* 8.0*C[4] */
L_tmp = L_sub(L_P[6], L_P[8]); /* -8.0*C[4] */
L_P[6] = L_add(L_tmp, L_shl(L_C[6], 1));
move32(); /* 2.0*C[6] */
L_tmp = L_shl(L_C[2], 5); /* 32.0*C[2] */
L_P[2] = L_sub(L_tmp, (256<<20));
move32();
L_tmp = L_add((1<<21)+1, L_C[8]);
L_tmp = L_shr(L_tmp, 1); /* 1+0.5*C[8] */
L_tmp = L_sub(L_tmp, L_C[2]);
L_tmp = L_add(L_tmp, L_C[4]);
L_P[8] = L_sub(L_tmp, L_C[6]);
move32();
return;
}
+423
View File
@@ -0,0 +1,423 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#define AMRWB_MAGIC_NUMBER "#!AMR-WB\n" /* defined in RFC4867 */
#define EVS_MAGIC_NUMBER "#!EVS_MC1.0\n" /* defined in 26.445 */
static const Word32 AMRWB_IOmode2rate[16] =
{
6600, /* AMRWB_IO_6600 */
8850, /* AMRWB_IO_8850 */
12650, /* AMRWB_IO_1265 */
14250, /* AMRWB_IO_1425 */
15850, /* AMRWB_IO_1585 */
18250, /* AMRWB_IO_1825 */
19850, /* AMRWB_IO_1985 */
23050, /* AMRWB_IO_2305 */
23850, /* AMRWB_IO_2385 */
1750, /* AMRWB_IO_SID */
-1, /* AMRWB_IO_FUT1 */
-1, /* AMRWB_IO_FUT2 */
-1, /* AMRWB_IO_FUT3 */
-1, /* AMRWB_IO_FUT4 */
0, /* SPEECH_LOST */
0 /* NO_DATA_TYPE */
};
static const Word32 PRIMARYmode2rate[16] =
{
2800, /* PRIMARY_2800 */
7200, /* PRIMARY_7200 */
8000, /* PRIMARY_8000 */
9600, /* PRIMARY_9600 */
13200, /* PRIMARY_13200 */
16400, /* PRIMARY_16400 */
24400, /* PRIMARY_24400 */
32000, /* PRIMARY_32000 */
48000, /* PRIMARY_48000 */
64000, /* PRIMARY_64000 */
96000, /* PRIMARY_96000 */
128000, /* PRIMARY_128000 */
2400, /* PRIMARY_SID */
-1, /* PRIMARY_FUT1 */
0, /* SPEECH_LOST */
0 /* NO_DATA_TYPE */
};
/* sorting tables for all AMR-WB IO modes */
static const Word16 sort_660[132] =
{
0, 5, 6, 7, 61, 84, 107, 130, 62, 85,
8, 4, 37, 38, 39, 40, 58, 81, 104, 127,
60, 83, 106, 129, 108, 131, 128, 41, 42, 80,
126, 1, 3, 57, 103, 82, 105, 59, 2, 63,
109, 110, 86, 19, 22, 23, 64, 87, 18, 20,
21, 17, 13, 88, 43, 89, 65, 111, 14, 24,
25, 26, 27, 28, 15, 16, 44, 90, 66, 112,
9, 11, 10, 12, 67, 113, 29, 30, 31, 32,
34, 33, 35, 36, 45, 51, 68, 74, 91, 97,
114, 120, 46, 69, 92, 115, 52, 75, 98, 121,
47, 70, 93, 116, 53, 76, 99, 122, 48, 71,
94, 117, 54, 77, 100, 123, 49, 72, 95, 118,
55, 78, 101, 124, 50, 73, 96, 119, 56, 79,
102, 125
};
static const Word16 sort_885[177] =
{
0, 4, 6, 7, 5, 3, 47, 48, 49, 112,
113, 114, 75, 106, 140, 171, 80, 111, 145, 176,
77, 108, 142, 173, 78, 109, 143, 174, 79, 110,
144, 175, 76, 107, 141, 172, 50, 115, 51, 2,
1, 81, 116, 146, 19, 21, 12, 17, 18, 20,
16, 25, 13, 10, 14, 24, 23, 22, 26, 8,
15, 52, 117, 31, 82, 147, 9, 33, 11, 83,
148, 53, 118, 28, 27, 84, 149, 34, 35, 29,
46, 32, 30, 54, 119, 37, 36, 39, 38, 40,
85, 150, 41, 42, 43, 44, 45, 55, 60, 65,
70, 86, 91, 96, 101, 120, 125, 130, 135, 151,
156, 161, 166, 56, 87, 121, 152, 61, 92, 126,
157, 66, 97, 131, 162, 71, 102, 136, 167, 57,
88, 122, 153, 62, 93, 127, 158, 67, 98, 132,
163, 72, 103, 137, 168, 58, 89, 123, 154, 63,
94, 128, 159, 68, 99, 133, 164, 73, 104, 138,
169, 59, 90, 124, 155, 64, 95, 129, 160, 69,
100, 134, 165, 74, 105, 139, 170
};
static const Word16 sort_1265[253] =
{
0, 4, 6, 93, 143, 196, 246, 7, 5, 3,
47, 48, 49, 50, 51, 150, 151, 152, 153, 154,
94, 144, 197, 247, 99, 149, 202, 252, 96, 146,
199, 249, 97, 147, 200, 250, 100, 203, 98, 148,
201, 251, 95, 145, 198, 248, 52, 2, 1, 101,
204, 155, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
156, 31, 102, 205, 9, 33, 11, 103, 206, 54,
157, 28, 27, 104, 207, 34, 35, 29, 46, 32,
30, 55, 158, 37, 36, 39, 38, 40, 105, 208,
41, 42, 43, 44, 45, 56, 106, 159, 209, 57,
66, 75, 84, 107, 116, 125, 134, 160, 169, 178,
187, 210, 219, 228, 237, 58, 108, 161, 211, 62,
112, 165, 215, 67, 117, 170, 220, 71, 121, 174,
224, 76, 126, 179, 229, 80, 130, 183, 233, 85,
135, 188, 238, 89, 139, 192, 242, 59, 109, 162,
212, 63, 113, 166, 216, 68, 118, 171, 221, 72,
122, 175, 225, 77, 127, 180, 230, 81, 131, 184,
234, 86, 136, 189, 239, 90, 140, 193, 243, 60,
110, 163, 213, 64, 114, 167, 217, 69, 119, 172,
222, 73, 123, 176, 226, 78, 128, 181, 231, 82,
132, 185, 235, 87, 137, 190, 240, 91, 141, 194,
244, 61, 111, 164, 214, 65, 115, 168, 218, 70,
120, 173, 223, 74, 124, 177, 227, 79, 129, 182,
232, 83, 133, 186, 236, 88, 138, 191, 241, 92,
142, 195, 245
};
static const Word16 sort_1425[285] =
{
0, 4, 6, 101, 159, 220, 278, 7, 5, 3,
47, 48, 49, 50, 51, 166, 167, 168, 169, 170,
102, 160, 221, 279, 107, 165, 226, 284, 104, 162,
223, 281, 105, 163, 224, 282, 108, 227, 106, 164,
225, 283, 103, 161, 222, 280, 52, 2, 1, 109,
228, 171, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
172, 31, 110, 229, 9, 33, 11, 111, 230, 54,
173, 28, 27, 112, 231, 34, 35, 29, 46, 32,
30, 55, 174, 37, 36, 39, 38, 40, 113, 232,
41, 42, 43, 44, 45, 56, 114, 175, 233, 62,
120, 181, 239, 75, 133, 194, 252, 57, 115, 176,
234, 63, 121, 182, 240, 70, 128, 189, 247, 76,
134, 195, 253, 83, 141, 202, 260, 92, 150, 211,
269, 84, 142, 203, 261, 93, 151, 212, 270, 85,
143, 204, 262, 94, 152, 213, 271, 86, 144, 205,
263, 95, 153, 214, 272, 64, 122, 183, 241, 77,
135, 196, 254, 65, 123, 184, 242, 78, 136, 197,
255, 87, 145, 206, 264, 96, 154, 215, 273, 58,
116, 177, 235, 66, 124, 185, 243, 71, 129, 190,
248, 79, 137, 198, 256, 88, 146, 207, 265, 97,
155, 216, 274, 59, 117, 178, 236, 67, 125, 186,
244, 72, 130, 191, 249, 80, 138, 199, 257, 89,
147, 208, 266, 98, 156, 217, 275, 60, 118, 179,
237, 68, 126, 187, 245, 73, 131, 192, 250, 81,
139, 200, 258, 90, 148, 209, 267, 99, 157, 218,
276, 61, 119, 180, 238, 69, 127, 188, 246, 74,
132, 193, 251, 82, 140, 201, 259, 91, 149, 210,
268, 100, 158, 219, 277
};
static const Word16 sort_1585[317] =
{
0, 4, 6, 109, 175, 244, 310, 7, 5, 3,
47, 48, 49, 50, 51, 182, 183, 184, 185, 186,
110, 176, 245, 311, 115, 181, 250, 316, 112, 178,
247, 313, 113, 179, 248, 314, 116, 251, 114, 180,
249, 315, 111, 177, 246, 312, 52, 2, 1, 117,
252, 187, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
188, 31, 118, 253, 9, 33, 11, 119, 254, 54,
189, 28, 27, 120, 255, 34, 35, 29, 46, 32,
30, 55, 190, 37, 36, 39, 38, 40, 121, 256,
41, 42, 43, 44, 45, 56, 122, 191, 257, 63,
129, 198, 264, 76, 142, 211, 277, 89, 155, 224,
290, 102, 168, 237, 303, 57, 123, 192, 258, 70,
136, 205, 271, 83, 149, 218, 284, 96, 162, 231,
297, 62, 128, 197, 263, 75, 141, 210, 276, 88,
154, 223, 289, 101, 167, 236, 302, 58, 124, 193,
259, 71, 137, 206, 272, 84, 150, 219, 285, 97,
163, 232, 298, 59, 125, 194, 260, 64, 130, 199,
265, 67, 133, 202, 268, 72, 138, 207, 273, 77,
143, 212, 278, 80, 146, 215, 281, 85, 151, 220,
286, 90, 156, 225, 291, 93, 159, 228, 294, 98,
164, 233, 299, 103, 169, 238, 304, 106, 172, 241,
307, 60, 126, 195, 261, 65, 131, 200, 266, 68,
134, 203, 269, 73, 139, 208, 274, 78, 144, 213,
279, 81, 147, 216, 282, 86, 152, 221, 287, 91,
157, 226, 292, 94, 160, 229, 295, 99, 165, 234,
300, 104, 170, 239, 305, 107, 173, 242, 308, 61,
127, 196, 262, 66, 132, 201, 267, 69, 135, 204,
270, 74, 140, 209, 275, 79, 145, 214, 280, 82,
148, 217, 283, 87, 153, 222, 288, 92, 158, 227,
293, 95, 161, 230, 296, 100, 166, 235, 301, 105,
171, 240, 306, 108, 174, 243, 309
};
static const Word16 sort_1825[365] =
{
0, 4, 6, 121, 199, 280, 358, 7, 5, 3,
47, 48, 49, 50, 51, 206, 207, 208, 209, 210,
122, 200, 281, 359, 127, 205, 286, 364, 124, 202,
283, 361, 125, 203, 284, 362, 128, 287, 126, 204,
285, 363, 123, 201, 282, 360, 52, 2, 1, 129,
288, 211, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
212, 31, 130, 289, 9, 33, 11, 131, 290, 54,
213, 28, 27, 132, 291, 34, 35, 29, 46, 32,
30, 55, 214, 37, 36, 39, 38, 40, 133, 292,
41, 42, 43, 44, 45, 56, 134, 215, 293, 198,
299, 136, 120, 138, 60, 279, 58, 62, 357, 139,
140, 295, 156, 57, 219, 297, 63, 217, 137, 170,
300, 222, 64, 106, 61, 78, 294, 92, 142, 141,
135, 221, 296, 301, 343, 59, 298, 184, 329, 315,
220, 216, 265, 251, 218, 237, 352, 223, 157, 86,
171, 87, 164, 351, 111, 302, 65, 178, 115, 323,
72, 192, 101, 179, 93, 73, 193, 151, 337, 309,
143, 274, 69, 324, 165, 150, 97, 338, 110, 310,
330, 273, 68, 107, 175, 245, 114, 79, 113, 189,
246, 259, 174, 71, 185, 96, 344, 100, 322, 83,
334, 316, 333, 252, 161, 348, 147, 82, 269, 232,
260, 308, 353, 347, 163, 231, 306, 320, 188, 270,
146, 177, 266, 350, 256, 85, 149, 116, 191, 160,
238, 258, 336, 305, 255, 88, 224, 99, 339, 230,
228, 227, 272, 242, 241, 319, 233, 311, 102, 74,
180, 275, 66, 194, 152, 325, 172, 247, 244, 261,
117, 158, 166, 354, 75, 144, 108, 312, 94, 186,
303, 80, 234, 89, 195, 112, 340, 181, 345, 317,
326, 276, 239, 167, 118, 313, 70, 355, 327, 253,
190, 176, 271, 104, 98, 153, 103, 90, 76, 267,
277, 248, 225, 262, 182, 84, 154, 235, 335, 168,
331, 196, 341, 249, 162, 307, 148, 349, 263, 321,
257, 243, 229, 356, 159, 119, 67, 187, 173, 145,
240, 77, 304, 332, 314, 342, 109, 254, 81, 278,
105, 91, 346, 318, 183, 250, 197, 328, 95, 155,
169, 268, 226, 236, 264
};
static const Word16 sort_1985[397] =
{
0, 4, 6, 129, 215, 304, 390, 7, 5, 3,
47, 48, 49, 50, 51, 222, 223, 224, 225, 226,
130, 216, 305, 391, 135, 221, 310, 396, 132, 218,
307, 393, 133, 219, 308, 394, 136, 311, 134, 220,
309, 395, 131, 217, 306, 392, 52, 2, 1, 137,
312, 227, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
228, 31, 138, 313, 9, 33, 11, 139, 314, 54,
229, 28, 27, 140, 315, 34, 35, 29, 46, 32,
30, 55, 230, 37, 36, 39, 38, 40, 141, 316,
41, 42, 43, 44, 45, 56, 142, 231, 317, 63,
73, 92, 340, 82, 324, 149, 353, 159, 334, 165,
338, 178, 163, 254, 77, 168, 257, 153, 343, 57,
248, 238, 79, 252, 166, 67, 80, 201, 101, 267,
143, 164, 341, 255, 339, 187, 376, 318, 78, 328,
362, 115, 232, 242, 253, 290, 276, 62, 58, 158,
68, 93, 179, 319, 148, 169, 154, 72, 385, 329,
333, 344, 102, 83, 144, 233, 323, 124, 243, 192,
354, 237, 64, 247, 202, 209, 150, 116, 335, 268,
239, 299, 188, 196, 298, 94, 195, 258, 123, 363,
384, 109, 325, 371, 170, 370, 84, 110, 295, 180,
74, 210, 191, 106, 291, 205, 367, 381, 377, 206,
355, 122, 119, 120, 383, 160, 105, 108, 277, 380,
294, 284, 285, 345, 208, 269, 249, 366, 386, 300,
297, 259, 125, 369, 197, 97, 194, 286, 211, 281,
280, 183, 372, 87, 155, 283, 59, 348, 327, 184,
76, 111, 330, 203, 349, 69, 98, 152, 145, 189,
66, 320, 337, 173, 358, 251, 198, 174, 263, 262,
126, 241, 193, 88, 388, 117, 95, 387, 112, 359,
287, 244, 103, 272, 301, 171, 162, 234, 273, 127,
373, 181, 292, 85, 378, 302, 121, 107, 364, 346,
356, 212, 278, 213, 65, 382, 288, 207, 113, 175,
99, 296, 374, 368, 199, 260, 185, 336, 331, 161,
270, 264, 250, 240, 75, 350, 151, 60, 89, 321,
156, 274, 360, 326, 70, 282, 167, 146, 352, 81,
91, 389, 266, 245, 177, 235, 190, 256, 204, 342,
128, 118, 303, 104, 379, 182, 114, 375, 200, 96,
293, 172, 214, 365, 279, 86, 289, 351, 347, 357,
261, 186, 176, 271, 90, 100, 147, 322, 275, 361,
71, 332, 61, 265, 157, 246, 236
};
static const Word16 sort_2305[461] =
{
0, 4, 6, 145, 247, 352, 454, 7, 5, 3,
47, 48, 49, 50, 51, 254, 255, 256, 257, 258,
146, 248, 353, 455, 151, 253, 358, 460, 148, 250,
355, 457, 149, 251, 356, 458, 152, 359, 150, 252,
357, 459, 147, 249, 354, 456, 52, 2, 1, 153,
360, 259, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
260, 31, 154, 361, 9, 33, 11, 155, 362, 54,
261, 28, 27, 156, 363, 34, 35, 29, 46, 32,
30, 55, 262, 37, 36, 39, 38, 40, 157, 364,
41, 42, 43, 44, 45, 56, 158, 263, 365, 181,
192, 170, 79, 57, 399, 90, 159, 297, 377, 366,
275, 68, 183, 388, 286, 194, 299, 92 , 70, 182,
401, 172, 59, 91, 58, 400, 368, 161, 81, 160,
264, 171, 80, 389, 390, 378, 379, 193, 298, 69,
266, 265, 367, 277, 288, 276, 287, 184, 60, 195,
82, 93, 71, 369, 402, 173, 162, 444, 300, 391,
98, 76, 278, 61, 267, 374, 135, 411, 167, 102,
380, 200, 87, 178, 65, 94, 204, 124, 72, 342,
189, 305, 381, 396, 433, 301, 226, 407, 289, 237,
113, 215, 185, 128, 309, 403, 116, 320, 196, 331,
370, 422, 174, 64, 392, 83, 425, 219, 134, 188,
432, 112, 427, 139, 279, 163, 436, 208, 447, 218,
236, 229, 97, 294, 385, 230, 166, 268, 177, 443,
225, 426, 101, 272, 138, 127, 290, 117, 347, 199,
414, 95, 140, 240, 410, 395, 209, 129, 283, 346,
105, 241, 437, 86, 308, 448, 203, 345, 186, 107,
220, 415, 334, 319, 106, 313, 118, 123, 73, 207,
421, 214, 384, 373, 438, 62, 371, 341, 75, 449,
168, 323, 164, 242, 416, 324, 304, 197, 335, 404,
271, 63, 191, 325, 96, 169, 231, 280, 312, 187,
406, 84, 201, 100, 67, 382, 175, 336, 202, 330,
269, 393, 376, 383, 293, 307, 409, 179, 285, 314,
302, 372, 398, 190, 180, 89, 99, 103, 232, 78,
88, 77, 136, 387, 165, 198, 394, 125, 176, 428,
74, 375, 238, 227, 66, 273, 282, 141, 306, 412,
114, 85, 130, 348, 119, 291, 296, 386, 233, 397,
303, 405, 284, 445, 423, 221, 210, 205, 450, 108,
274, 434, 216, 343, 337, 142, 243, 321, 408, 451,
310, 292, 120, 109, 281, 439, 270, 429, 332, 295,
418, 211, 315, 222, 326, 131, 430, 244, 327, 349,
417, 316, 143, 338, 440, 234, 110, 212, 452, 245,
121, 419, 350, 223, 132, 441, 328, 413, 317, 339,
126, 104, 137, 446, 344, 239, 435, 115, 333, 206,
322, 217, 228, 424, 453, 311, 351, 111, 442, 224,
213, 122, 431, 340, 235, 246, 133, 144, 420, 329,
318
};
static const Word16 sort_2385[477] =
{
0, 4, 6, 145, 251, 360, 466, 7, 5, 3,
47, 48, 49, 50, 51, 262, 263, 264, 265, 266,
146, 252, 361, 467, 151, 257, 366, 472, 148, 254,
363, 469, 149, 255, 364, 470, 156, 371, 150, 256,
365, 471, 147, 253, 362, 468, 52, 2, 1, 157,
372, 267, 19, 21, 12, 17, 18, 20, 16, 25,
13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
268, 31, 152, 153, 154, 155, 258, 259, 260, 261,
367, 368, 369, 370, 473, 474, 475, 476, 158, 373,
9, 33, 11, 159, 374, 54, 269, 28, 27, 160,
375, 34, 35, 29, 46, 32, 30, 55, 270, 37,
36, 39, 38, 40, 161, 376, 41, 42, 43, 44,
45, 56, 162, 271, 377, 185, 196, 174, 79, 57,
411, 90, 163, 305, 389, 378, 283, 68, 187, 400,
294, 198, 307, 92, 70, 186, 413, 176, 59, 91,
58, 412, 380, 165, 81, 164, 272, 175, 80, 401,
402, 390, 391, 197, 306, 69, 274, 273, 379, 285,
296, 284, 295, 188, 60, 199, 82, 93, 71, 381,
414, 177, 166, 456, 308, 403, 98, 76, 286, 61,
275, 386, 135, 423, 171, 102, 392, 204, 87, 182,
65, 94, 208, 124, 72, 350, 193, 313, 393, 408,
445, 309, 230, 419, 297, 241, 113, 219, 189, 128,
317, 415, 116, 328, 200, 339, 382, 434, 178, 64,
404, 83, 437, 223, 134, 192, 444, 112, 439, 139,
287, 167, 448, 212, 459, 222, 240, 233, 97, 302,
397, 234, 170, 276, 181, 455, 229, 438, 101, 280,
138, 127, 298, 117, 355, 203, 426, 95, 140, 244,
422, 407, 213, 129, 291, 354, 105, 245, 449, 86,
316, 460, 207, 353, 190, 107, 224, 427, 342, 327,
106, 321, 118, 123, 73, 211, 433, 218, 396, 385,
450, 62, 383, 349, 75, 461, 172, 331, 168, 246,
428, 332, 312, 201, 343, 416, 279, 63, 195, 333,
96, 173, 235, 288, 320, 191, 418, 84, 205, 100,
67, 394, 179, 344, 206, 338, 277, 405, 388, 395,
301, 315, 421, 183, 293, 322, 310, 384, 410, 194,
184, 89, 99, 103, 236, 78, 88, 77, 136, 399,
169, 202, 406, 125, 180, 440, 74, 387, 242, 231,
66, 281, 290, 141, 314, 424, 114, 85, 130, 356,
119, 299, 304, 398, 237, 409, 311, 417, 292, 457,
435, 225, 214, 209, 462, 108, 282, 446, 220, 351,
345, 142, 247, 329, 420, 463, 318, 300, 120, 109,
289, 451, 278, 441, 340, 303, 430, 215, 323, 226,
334, 131, 442, 248, 335, 357, 429, 324, 143, 346,
452, 238, 110, 216, 464, 249, 121, 431, 358, 227,
132, 453, 336, 425, 325, 347, 126, 104, 137, 458,
352, 243, 447, 115, 341, 210, 330, 221, 232, 436,
465, 319, 359, 111, 454, 228, 217, 122, 443, 348,
239, 250, 133, 144, 432, 337, 326
};
static const Word16 sort_SID[35] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34
};
/* pointer table for bit sorting tables */
static const Word16 * const sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305,
sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL
};
/* 4 bit to 3 bit AMR-WB CMR remapping table */
static const Word16 amrwb_3bit_cmr[16] =
{
0x00, /* AMRWB_660 */
0x01, /* AMRWB_885 */
0x02, /* AMRWB_1265 */
0x05, /* AMRWB_1425 */
0x03, /* AMRWB_1585 */
0x06, /* AMRWB_1825 */
0x06, /* AMRWB_1985 -> AMRWB_1825 */
0x06, /* AMRWB_2305 -> AMRWB_1825 */
0x04, /* AMRWB_2385 */
0x07, /* invalid request -> none */
0x07, /* invalid request -> none */
0x07, /* invalid request -> none */
0x07, /* invalid request -> none */
0x07, /* invalid request -> none */
0x07, /* invalid request -> none */
0x07 /* invalid request -> none */
};
/* 3 bit to 4 bit AMR-WB CMR remapping table */
static const Word16 amrwb_4bit_cmr[8] =
{
0x00, /* AMRWB_660 */
0x01, /* AMRWB_885 */
0x02, /* AMRWB_1265 */
0x04, /* AMRWB_1585 */
0x08, /* AMRWB_2385 */
0x03, /* AMRWB_1425 */
0x05, /* AMRWB_1825 */
0x0f /* invalid */
};
File diff suppressed because it is too large Load Diff
+882
View File
@@ -0,0 +1,882 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include "prot_fx.h"
#include "rom_com_fx.h"
#include "cnst_fx.h"
#include "stl.h"
/*-----------------------------------------------------------------*
* Local functions
*-----------------------------------------------------------------*/
static void make_offset_scale_fx( Word16 j, const Word32 tab_no_cv[], const Word16 no_ld[],
Word16 no_scl, Word32 offset_scale[][MAX_NO_SCALES+1]);
static void init_offset_fx( Word32 offset_scale1[][MAX_NO_SCALES+1], Word32 offset_scale2[][MAX_NO_SCALES+1],
Word32 offset_scale1_p[][MAX_NO_SCALES+1], Word32 offset_scale2_p[][MAX_NO_SCALES+1],
Word16 no_scales[][2], Word16 no_scales_p[][2]);
static void decode_comb_fx(Word32 index,Word16 *cv,Word16 idx_lead);
static void decode_sign_pc1_fx( Word16 *c, Word16 idx_sign, Word16 parity );
static void put_value_fx(Word16 *cv, Word16 *p, Word16 val, Word16 dim, Word16 no_new_val);
static void decode_leaders_fx(Word16 index, Word16 idx_lead, Word16 *cv );
static void idx2c_fx(Word16 n, Word16 *p, Word16 k, Word16 val );
static void divide_64_32_fx(Word16 *xs,Word32 y, Word32 *result, Word32 *rem);
static Word16
decode_indexes_fx(Word16 * index,Word16 no_bits,const Word16 * p_scales, Word16 * p_no_scales,
Word32 * p_offset_scale1, Word32 * p_offset_scale2,Word16 * x_lvq,Word16 mode_glb, Word16 *scales);
static Word32 divide_32_32_fx(Word32 y, Word32 x, Word32 * rem);
static Word16 divide_16_16_fx(Word16 y, Word16 x, Word16 *rem);
/* used in CNG-LP coding */
void permute_fx(
Word16 *pTmp1, /* i/o: vector whose components are to be permuted */
const Word16 *perm /* i : permutation info (indexes that should be interchanged), max two perms */
)
{
Word16 p1, p2;
Word16 tmp;
p1 = perm[0];
move16();
p2 = perm[1];
move16();
tmp = pTmp1[p1];
move16();
pTmp1[p1] = pTmp1[p2];
move16();
move16();
pTmp1[p2] = tmp;
move16();
p1 = perm[2];
move16();
IF ( add(p1, 1) > 0 )
{
p2 = perm[3];
move16();
tmp = pTmp1[p1];
move16();
pTmp1[p1] = pTmp1[p2];
move16();
move16();
pTmp1[p2] = tmp;
move16();
}
return;
}
void init_lvq_fx(
Word32 offset_scale1[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - safety net structures*/
Word32 offset_scale2[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - safety net structures*/
Word32 offset_scale1_p[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - predictive structures*/
Word32 offset_scale2_p[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - predictive structures*/
Word16 no_scales[][2], /* o: number of truncations for each LSF subvector at each MSLVQ structure - safety net */
Word16 no_scales_p[][2] /* o: number of truncations for each LSF subvector at each MSLVQ structure - predictive */
)
{
Word16 i, j;
/* safety-net mode */
FOR(i=0; i<MAX_NO_MODES; i++)
{
j=0;
move16();
test();
WHILE ((sub(j,MAX_NO_SCALES)<0) && (no_lead_fx[i][j] >0 ))
{
j++;
}
no_scales[i][0] = j;
move16();
j = MAX_NO_SCALES;
move16();
test();
WHILE ((sub(j,shl(MAX_NO_SCALES,1))<0) && (no_lead_fx[i][j] >0 ))
{
j++;
}
no_scales[i][1] = sub(j, MAX_NO_SCALES);
move16();
}
/* predictive mode */
FOR(i=0; i<MAX_NO_MODES_p; i++)
{
j=0;
move16();
WHILE ((sub(j,MAX_NO_SCALES)<0) && (no_lead_p_fx[i][j] >0 ))
{
j++;
}
no_scales_p[i][0] = j;
move16();
j = MAX_NO_SCALES;
move16();
WHILE ((sub(j, shl(MAX_NO_SCALES,1))<0) && (no_lead_p_fx[i][j] >0 ))
{
j++;
}
no_scales_p[i][1] = sub(j,MAX_NO_SCALES);
move16();
}
/* index offsets for each truncation */
init_offset_fx( offset_scale1, offset_scale2, offset_scale1_p, offset_scale2_p, no_scales, no_scales_p );
}
/* make_offset_scale_fx() - calculates scale offset values for a particular MSLVQ structure */
static
void make_offset_scale_fx(
Word16 j, /* i: MSLVQ structure index */
const Word32 tab_no_cv[], /* i: cummulated number of codevectors in each leader class */
const Word16 no_ld[], /* i: number of leaders in each truncation for the MSLVQ structure j*/
Word16 no_scl, /* i: number of truncations in the MSLVQ structure j */
Word32 offset_scale[][MAX_NO_SCALES+1]/* o: offset values */
)
{
Word16 i;
offset_scale[j][0] = L_deposit_l(1);
FOR( i=1; i<=no_scl; i++ )
{
offset_scale[j][i] = L_add(offset_scale[j][sub(i,1)], tab_no_cv[no_ld[sub(i,1)]]);
move32();
}
return;
}
void init_offset_fx(
Word32 offset_scale1[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - safety net structures*/
Word32 offset_scale2[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - safety net structures*/
Word32 offset_scale1_p[][MAX_NO_SCALES+1],/* o: lattice truncation index offset for the first LSF subvector - predictive structures*/
Word32 offset_scale2_p[][MAX_NO_SCALES+1],/* o: lattice truncation index offset for the second LSF subvector - predictive structures*/
Word16 no_scales[][2], /* i: number of truncations for each LSF subvector at each MSLVQ structure - safety net */
Word16 no_scales_p[][2] /* i: number of truncations for each LSF subvector at each MSLVQ structure - predictive */
)
{
Word16 j;
/* safety-net */
FOR( j=0; j<MAX_NO_MODES; j++ )
{
make_offset_scale_fx( j, table_no_cv_fx, no_lead_fx[j], no_scales[j][0], offset_scale1 );
make_offset_scale_fx( j, table_no_cv_fx, &no_lead_fx[j][MAX_NO_SCALES], no_scales[j][1], offset_scale2 );
}
/* predictive modes AR and MA */
FOR( j=0; j<MAX_NO_MODES_p; j++ )
{
make_offset_scale_fx(j, table_no_cv_fx, no_lead_p_fx[j], no_scales_p[j][0], offset_scale1_p);
make_offset_scale_fx(j, table_no_cv_fx, &no_lead_p_fx[j][MAX_NO_SCALES], no_scales_p[j][1], offset_scale2_p);
}
offset_scale1[MAX_NO_MODES][0] = 1;
move32();
offset_scale2[MAX_NO_MODES][0] = 1;
move32();
offset_scale1_p[MAX_NO_MODES_p][0] = 1;
move32();
offset_scale2_p[MAX_NO_MODES_p][0] = 1;
move32();
return;
}
static Word16
decode_indexes_fx(
Word16 * index, /* i: LSF vector index, written as array of Word16 because it generally uses more than 16 bits */
Word16 no_bits, /* i: number of bits for the index */
const Word16 * p_scales, /* i: scale values for the MSLVQ structures */
Word16 * p_no_scales, /* i: number of truncations for each MSLVQ structure */
Word32 * p_offset_scale1, /* i: scale index offset for first LSF subvector */
Word32 * p_offset_scale2, /* i: scale index offset for second LSF subvector */
Word16 * x_lvq, /* o: decoded LSF vector in Q1 */
Word16 mode_glb, /* i: index of LSLVQ structure */
Word16 * scales /* o: scale values for the decoded MSLVQ LSF codevector */
)
{
Word32 index1=0, index2=0;
Word16 len_scales = MAX_NO_SCALES*2, no_modes;
Word16 i, im1, idx_scale;
Word16 tmp;
no_modes = MAX_NO_SCALES+1;
move16();
IF (sub(no_bits,shl(LEN_INDICE,1)) <= 0) /* the third short is not used */
{
index[2] = 0;
move16();
if ( sub(no_bits,LEN_INDICE) <= 0 )
{
index[1] =0;
move16();
}
}
/* safety check in case of bit errors */
FOR( i = 0; i<3; i++ )
{
IF( index[i] < 0 )
{
set16_fx( x_lvq, 0, 2*LATTICE_DIM );
scales[0] = 0;
scales[1] = 0;
index[i] = 0;
return 1;
}
}
/* first subvector */
tmp = i_mult2(mode_glb,no_modes);
IF ( p_offset_scale2[add(tmp, p_no_scales[add(shl(mode_glb,1),1)])] > 0 )
{
divide_64_32_fx( index, p_offset_scale2[tmp+ p_no_scales[add(shl(mode_glb,1),1)]], &index1, &index2 );
}
ELSE
{
index1 = L_deposit_l(index[0]); /* this is for very low bitrates, so there is no loss in truncation */
index2 = L_deposit_l(0);
}
IF ( index1 == 0 )
{
FOR( i=0; i<LATTICE_DIM; i++ )
{
x_lvq[i] = 0;
move16();
}
scales[0] = 0;
}
ELSE
{
IF( L_sub(index1, p_offset_scale1[mode_glb*no_modes+p_no_scales[mode_glb*2]]) >= 0 )
{
/* safety check in case of bit errors */
set16_fx( x_lvq, 0, 2*LATTICE_DIM );
scales[0] = 0;
scales[1] = 0;
return 1;
}
/* find idx_scale */
i = 1;
move16();
WHILE( sub(i, p_no_scales[mode_glb*2]) <= 0 && L_sub(index1, p_offset_scale1[mode_glb*no_modes +i])>= 0 )
{
i = add(i,1);
}
idx_scale = sub(i,1);
move16();
index1 = L_sub(index1, p_offset_scale1[tmp+idx_scale]);
/* find idx_leader */
i = 1;
move16();
WHILE( L_sub(index1, table_no_cv_fx[i]) >= 0 )
{
i = add(i, 1);
}
im1 = sub(i,1);
decode_comb_fx(L_sub(index1,table_no_cv_fx[im1]), x_lvq, im1 );
scales[0] = p_scales[mode_glb*len_scales+idx_scale];
}
/* second subvector */
IF ( index2 == 0 )
{
FOR( i=LATTICE_DIM; i<2*LATTICE_DIM; i++ )
{
x_lvq[i] = 0;
move16();
}
scales[1] = 0;
move16();
}
ELSE
{
/* find the index for the scale/truncation */
i = 1;
move16();
WHILE( L_sub(index2, p_offset_scale2[tmp+i]) >= 0 )
{
i = add(i, 1);
}
idx_scale = sub(i,1);
index2 = L_sub(index2, p_offset_scale2[add(tmp,idx_scale)]);
/* find the index of the leader vector */
i = 1;
move16();
WHILE ( L_sub(index2, table_no_cv_fx[i]) >= 0 )
{
i = add(i, 1);
}
im1 = sub(i,1);
decode_comb_fx( index2-table_no_cv_fx[im1], &x_lvq[LATTICE_DIM], im1 );
scales[1] = p_scales[add(i_mult2(mode_glb,len_scales),add(MAX_NO_SCALES,idx_scale))];
move16();
}
return 0;
}
Word16 deindex_lvq_fx(
Word16 *index, /* i : index to be decoded, as an array of 3 Word16 */
Word16 *x_lvq, /* o : decoded codevector Q(x2.56) */
Word16 mode, /* i : LVQ coding mode/MSLVQ structure index (select scales & no_lead ), or idx_cv for CNG case */
Word16 sf_flag, /* i : safety net flag */
Word16 no_bits, /* i : number of bits for lattice */
Word32 *p_offset_scale1, /* i : offset for first subvector */
Word32 *p_offset_scale2, /* i : offset for the second subvector */
Word16 *p_no_scales /* i : number of scales for each truncation and each MSLVQ structure */
)
{
Word16 i;
const Word16 * p_scales;
Word16 mode_glb;
Word32 L_tmp;
Word16 scales[2];
Word16 ber_flag;
IF ( sub(sf_flag,1) == 0 )
{
mode_glb = add(offset_lvq_modes_SN_fx[mode], offset_in_lvq_mode_SN_fx[mode][sub(no_bits,min_lat_bits_SN_fx[mode])]);
p_scales = &scales_fx[0][0];
move16();
}
ELSE
{
mode_glb = add(offset_lvq_modes_pred_fx[mode], offset_in_lvq_mode_pred_fx[mode][sub(no_bits,min_lat_bits_pred_fx[mode])]);
p_scales = &scales_p_fx[0][0];
move16();
}
/* decode the lattice index into the lattice codevectors for the two subvectors */
ber_flag =
decode_indexes_fx( index, no_bits, p_scales, p_no_scales, p_offset_scale1,
p_offset_scale2, x_lvq, mode_glb, scales ); /* x_lvq is here Q1 */
IF ( sub(sf_flag,1) == 0 )
{
/* safety-net case*/
IF(scales[0])
{
FOR( i=0; i<LATTICE_DIM; i++ )
{
L_tmp = L_mult(x_lvq[i],scales[0]); /* Q1+Q11+Q1 = Q13 */
/* Increase calculation accuracy by shifting more to the left and using rounding instead of truncation*/
L_tmp = L_shl(Mult_32_16(L_tmp, shl(sigma_MSLVQ_fx[mode][i], 3)), 15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
}
IF (scales[1])
{
FOR( i=LATTICE_DIM; i<2*LATTICE_DIM; i++ )
{
L_tmp = L_mult(x_lvq[i],scales[1]); /* Q1+Q11+Q1 = Q13 */
L_tmp = L_shl(Mult_32_16(L_tmp, shl(sigma_MSLVQ_fx[mode][i], 3)), 15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
}
}
ELSE
{
/* predictive mode AR or MA */
IF(scales[0])
{
FOR( i=0; i<LATTICE_DIM; i++ )
{
L_tmp = L_mult(x_lvq[i],scales[0]); /* Q1+Q11+Q1 = Q13 */
L_tmp = L_shl(Mult_32_16(L_tmp,shl(sigma_p_fx[mode][i],3)),15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
}
IF (scales[1])
{
FOR( i=LATTICE_DIM; i<2*LATTICE_DIM; i++ )
{
L_tmp = L_mult(x_lvq[i],scales[1]); /* Q1+Q11+Q1 = Q13 */
L_tmp = L_shl(Mult_32_16(L_tmp,shl(sigma_p_fx[mode][i],3)),15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
}
}
return ber_flag;
}
/*----------------------------------------------------------------------------------------------------*
* deindex_lvq_cng()
* Note:
* The sampling frequency for the LVQ CNG decoder frame can be determined by checking the fully decoded
* value of the highest order LSF coefficient. Thus sampling rate information, nor extra codebooks are
* not needed for deindex_lvq_cng(), since it is embedded inside the LSF codebooks.
*----------------------------------------------------------------------------------------------------*/
Word16 deindex_lvq_cng_fx(
Word16 *index, /* i: index to be decoded, as an array of 3 short */
Word16 *x_lvq, /* o: decoded codevector Q9 */
Word16 idx_cv, /* i: relative mode_lvq, wrt START_CNG */
Word16 no_bits, /* i: number of bits for lattice */
Word32 * p_offset_scale1, /* i: scale index offset for first LSF subvector */
Word32 * p_offset_scale2, /* i: scale index offset for second LSF subvector */
Word16 * p_no_scales /* i: number of scales for each MSLVQ structure and each subvector */
)
{
Word16 i;
Word32 L_tmp;
const Word16 *p_scales;
Word16 mode_glb, mode;
Word16 scales[2];
Word16 ber_flag;
/* the MSLVQ structure in the second LP-CNG stage depends on the index from the first stage */
mode_glb = add(START_CNG, idx_cv);
mode = add(LVQ_COD_MODES, idx_cv);
p_scales = &scales_fx[0][0];
move16();
ber_flag =
decode_indexes_fx( index, no_bits, p_scales, p_no_scales, p_offset_scale1, p_offset_scale2, x_lvq, mode_glb ,scales);
FOR(i=0; i<LATTICE_DIM; i++)
{
L_tmp = L_mult(x_lvq[i],scales[0]); /* Q1+Q11+Q1 = Q13 */
L_tmp = L_shl(Mult_32_16(L_tmp, shl(sigma_MSLVQ_fx[mode][i], 3)), 15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
FOR(i=LATTICE_DIM; i<2*LATTICE_DIM; i++)
{
L_tmp = L_mult(x_lvq[i],scales[1]); /* Q1+Q11+Q1 = Q13 */
L_tmp = L_shl(Mult_32_16(L_tmp, shl(sigma_MSLVQ_fx[mode][i], 3)), 15); /* Q13 + Q2 +x2.56 -Q15 */
x_lvq[i]= round_fx(L_tmp);
}
/* check if permutting needed */
IF ( cng_sort_fx[idx_cv] )
{
permute_fx( x_lvq, perm_MSLVQ_fx[idx_cv] );
}
return ber_flag;
}
/* combinatorial indexing */
static void idx2c_fx(
Word16 n, /* i : total number of positions (components)*/
Word16 *p, /* o : array with positions of the k components */
Word16 k, /* i : number of components whose position is to be determined */
Word16 val /* i : index to be decoded */
)
{
Word16 i, skip, pos, k1;
skip = 0;
move16();
pos = 0;
move16();
k1 = sub(k,1);
move16();
WHILE( sub(add(skip, sub(C_VQ_fx[n-pos-1][k1] ,1)), val) < 0 )
{
skip = add(skip, C_VQ_fx[n-pos-1][k1]);
move16();
pos++;
move16();
}
p[0] = pos;
move16();
n = sub(n,add(pos,1));
val = sub(val,skip);
IF ( sub(k, 1) == 0 )
{
return;
}
idx2c_fx( n, p+1, k1, val );
/* pos+1 */
FOR( i=1; i<k; i++ )
{
p[i] = add(p[i], add(pos,1));
move16();
}
return;
}
/* combinatorial deindexing */
static void decode_comb_fx(
Word32 index, /* i : index to be decoded */
Word16 *cv, /* o : decoded codevector Q1*/
Word16 idx_lead /* i : leader class index */
)
{
Word16 idx_sign;
idx_sign = extract_l(div_l(L_shl(index,1), pi0_fx[idx_lead])); /*(index/pi0_fx[idx_lead]); */
index = L_sub(index, L_mult0(idx_sign, pi0_fx[idx_lead]));
decode_leaders_fx(extract_l(index), idx_lead, cv);
decode_sign_pc1_fx(cv, idx_sign, pl_par_fx[idx_lead]);
return;
}
void decode_sign_pc1_fx(
Word16 *c, /* o : decoded codevector Q1*/
Word16 idx_sign, /* i : sign index */
Word16 parity /* i : parity flag (+1/-1/0) */
)
{
Word16 i, len = LATTICE_DIM, cnt_neg = 1;
if ( parity )
{
len = sub(len,1);
}
FOR( i=0; i<len; i++ )
{
IF (c[i] > 0)
{
/*if (idx_sign % 2) */
IF(s_and(idx_sign,1))
{
c[i] = negate(c[i]);
move16();
cnt_neg = negate(cnt_neg);
move16();
}
idx_sign = shr(idx_sign,1); /* >>= 1; */
}
}
IF ( sub(len, LATTICE_DIM)<0 )
{
IF (sub(cnt_neg, parity) != 0)
{
c[len] = negate(c[len]);
move16();
}
}
return;
}
/*-----------------------------------------------------------------*
* multiply32_32_64_fx()
*
* (function for int64 )
*-----------------------------------------------------------------*/
void multiply32_32_64_fx(
Word32 x, /* i: first factor */
Word32 y, /* i: second factor */
Word32 *res /* o: multiplication result as array of 2 Word32*/
)
{
Word32 tmp, high;
Word16 x_tmp[2], y_tmp[2];
x_tmp[0] = extract_l(L_and(x, 0x7fff)); /*extract_l(x); */ /* lowest 16 bits */
x_tmp[1] = extract_l(L_and(L_shr(x,15),0x7fff)); /*extract_h(x); */
y_tmp[0] = extract_l(L_and(y, 0x7fff)); /*extract_l(y); */
y_tmp[1] = extract_l(L_and(L_shr(y,15),0x7fff)); /*extract_h(y); */
tmp = L_mult0(x_tmp[0], y_tmp[0]);
high = L_shr(tmp,15); /*extract_h(tmp); */
res[0] = L_and(tmp, 0x7fff); /* extract_l(tmp); */
tmp = L_mac0(L_mac0(high, x_tmp[1], y_tmp[0]), x_tmp[0],y_tmp[1]); /* x and y are not using all 32 bits, so this is valid */
high = L_shr(tmp,15);/*extract_h(tmp); */
res[0] = L_add(res[0], L_shl(L_and(tmp,0x7fff), 15));
move32();
res[1] = L_mac0(high, x_tmp[1], y_tmp[1]);
move32();
return;
}
static void decode_leaders_fx(
Word16 index, /* i : index to be decoded */
Word16 idx_lead, /* i : leader class index */
Word16 *cv /* o : decoded codevector Q1*/
)
{
Word16 i, no_vals_loc, no_vals_last, p[LATTICE_DIM], dim_loc, n_crt;
Word16 index1;
Word16 val_crt;
no_vals_loc = no_vals_fx[idx_lead];
move16();
val_crt = vals_fx[idx_lead][no_vals_loc-1];
move16(); /*Q1 */
no_vals_last = no_vals_ind_fx[idx_lead][no_vals_loc-1];
move16();
FOR( i=0; i<no_vals_last; i++ )
{
cv[i] = val_crt;
move16(); /*Q1 */
}
val_crt = 1;
move16();
dim_loc = no_vals_last;
move16();
SWITCH ( no_vals_loc )
{
case 1:
BREAK;
case 2:
idx2c_fx(LATTICE_DIM, p, no_vals_ind_fx[idx_lead][0], index);
put_value_fx(cv, p, vals_fx[idx_lead][0], no_vals_last, no_vals_ind_fx[idx_lead][0]);
BREAK;
case 4:
dim_loc = add(dim_loc,no_vals_ind_fx[idx_lead][2]);
n_crt = no_vals_ind_fx[idx_lead][2];
index1 = divide_16_16_fx(index, C_VQ_fx[dim_loc][n_crt], &index); /* index1 = index/C_VQ_fx[dim_loc][n_crt]; */
/*index = sub(index, i_mult2(index1, C_VQ_fx[dim_loc][n_crt]) ); */ /* index-= index1*C_VQ_fx[dim_loc][n_crt]; */ move16();
idx2c_fx(dim_loc, p, n_crt, index);
put_value_fx(cv, p, vals_fx[idx_lead][2], no_vals_last, no_vals_ind_fx[idx_lead][2]); /* Q1 */
index = index1;
move16();
/* no break */
case 3:
dim_loc = add(dim_loc, no_vals_ind_fx[idx_lead][1]);
n_crt = no_vals_ind_fx[idx_lead][1];
move16();
index1 = divide_16_16_fx(index, C_VQ_fx[dim_loc][n_crt], &index);
/*index = sub(index, i_mult2(index1, C_VQ_fx[dim_loc][n_crt]));move16(); */
idx2c_fx(dim_loc, p, n_crt, index);
put_value_fx(cv, p, vals_fx[idx_lead][1], sub(dim_loc, n_crt), n_crt);
idx2c_fx(LATTICE_DIM, p, no_vals_ind_fx[idx_lead][0], index1);
move16();
put_value_fx(cv, p, vals_fx[idx_lead][0], dim_loc, no_vals_ind_fx[idx_lead][0]);
BREAK;
}
return;
}
/* divide_32_32_fx() :Division reminder - rem is the reminder of the division between y and x. */
static Word32 divide_32_32_fx(Word32 y, /* i */
Word32 x, /* i */
Word32 *rem /* o */
)
{
Word32 result, t, L_tmp;
Word16 i, ny, nx, nyx;
IF (L_sub(y, x) < 0)
{
result = L_deposit_l(0);
*rem = y;
move32();
}
ELSE
{
result = L_deposit_l(0);
IF (y==0)
{
ny = 0;
move16();
}
ELSE
{
ny = sub(31, norm_l(y));
}
IF (x==0)
{
nx = 0;
move16();
}
ELSE
{
nx = sub(31, norm_l(x));
}
nyx = sub(ny,nx);
/*t = L_and(L_shr(y, add(nyx,1)),sub(shl(1,sub(nx,1)),1)); */
t = L_shr(y,add(nyx,1));
FOR(i=0; i<=nyx; i++)
{
t = L_add(L_shl(t,1), L_and(L_shr(y,sub(nyx,i)),1)); /* L_and(y,L_shl(1, sub(nyx,i)))); */
result = L_shl(result,1);
L_tmp = L_sub(t,x);
IF(L_tmp >= 0)
{
result = L_add(result,1);
t = L_add(L_tmp, 0);
}
}
*rem = t;
move32();
}
return result;
}
/* divide_32_32_fx() :Division reminder for Word16 - rem is the reminder of the division between y and x. */
static Word16 divide_16_16_fx(Word16 y, /* i */
Word16 x, /* i */
Word16 *rem /* o */
)
{
Word16 result, t, tmp;
Word16 i, ny, nx, nyx;
IF (L_sub(y, x) < 0)
{
result = 0;
move16();
*rem = y;
move16();
}
ELSE
{
result = 0;
move16();
IF (y==0)
{
ny = 0;
move16();
}
ELSE
{
ny = sub(15, norm_s(y));
}
IF (x==0)
{
nx = 0;
move16();
}
ELSE
{
nx = sub(15, norm_s(x));
}
nyx = sub(ny,nx);
t = s_and(shr(y, add(nyx,1)),sub(shl(1,sub(nx,1)),1));
FOR(i=0; i<=nyx; i++)
{
t = add(shl(t,1), s_and(shr(y,sub(nyx,i)),1)); /* L_and(y,L_shl(1, sub(nyx,i)))); */
result = shl(result,1);
tmp = sub(t,x);
IF(tmp >= 0)
{
result = add(result,1);
t = tmp;
move16();
}
}
*rem = t;
move16();
}
return result;
}
static void divide_64_32_fx(
Word16 *xs, /* i : denominator as array of two int32 */
Word32 y, /* i : nominator on 32 bits */
Word32 *result, /* o : integer division result on 32 bits */
Word32 *rem /* o : integer division reminder on 32 bits */
)
{
Word16 nb_x1;
Word32 r, x_tmp, x[2], q, q1;
x[0] = L_add(L_add(L_shl(L_deposit_l(s_and(xs[2],1)),2*LEN_INDICE),L_shl(L_deposit_l(xs[1]), LEN_INDICE)),L_deposit_l(xs[0]));
move32();
x[1] = L_shr(L_deposit_l(xs[2]),1);
move32();
/*x[0] = (((xs[2])&(1)<<(LEN_INDICE*2)) + (xs[1]<<LEN_INDICE) + xs[0];
x[1] = xs[2]>>1; */
IF (x[1] ==0)
{
nb_x1 = 0;
move16();
}
ELSE
{
nb_x1 = sub(31, norm_l(x[1])); /*get_no_bits_fx(x[1]); */
}
/* take the first 31 bits */
IF ( nb_x1 > 0 )
{
x_tmp = L_add(L_shl(x[1],sub(31,nb_x1)),L_shr(x[0], nb_x1));
/* x_tmp = (x[1]<<(32-nb_x1)) + (x[0]>>nb_x1); */
q = divide_32_32_fx(x_tmp,y, &r); /* q = x_tmp/y, reminder r */
r = L_add(L_shl(r, nb_x1), L_and(x[0],L_deposit_l(sub(shl(1,nb_x1),1)))); /* this is the first reminder */
/* r = (r<<nb_x1)+(x[0]&((1<<nb_x1) - 1)); */
q1 = divide_32_32_fx(r, y, rem);
*result = L_add(L_shl(q,nb_x1), q1);
move32();
}
ELSE
{
*result = divide_32_32_fx(x[0], y, rem);
move32();
}
return;
}
static void put_value_fx(
Word16 *cv, /* i/o : input codevector Q1*/
Word16 *p, /* i : array with positions */
Word16 val, /* i : value to be inserted Q1*/
Word16 dim, /* i : vector dimension */
Word16 no_new_val /* i : number of values to be inserted */
)
{
Word16 cv_out[LATTICE_DIM];
Word16 i, occ[LATTICE_DIM], cnt, limit;
limit = add(dim, no_new_val);
FOR( i=0; i<limit; i++ )
{
occ[i] = 0;
move16();
}
FOR( i=0; i<no_new_val; i++ )
{
cv_out[p[i]] = val;
move16();
occ[p[i]] = 1;
move16();
}
cnt = 0;
move16();
FOR( i=0; i<limit; i++ )
{
if (occ[i] == 0)
{
cv_out[i] = cv[cnt++];
move16();
}
}
FOR( i=0; i<limit; i++ )
{
cv[i] = cv_out[i];
move16();
}
return;
}
+218
View File
@@ -0,0 +1,218 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "rom_com_fx.h"
#include "prot_fx.h"
#include "stl.h"
/*===================================================================*/
/* FUNCTION : dequantize_uvg_fx() */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function returns the quantized gain
vector given the indices in the gain
quantization tables */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) iG1 : index into UVG1CB_fx table (Q0) */
/* _ (Word16*) iG2 : indices into UVG2CB_fx (Q0) */
/* - (Word32) Fs : output sampling rate */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) G : Output quantized gain vector */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
Word16 dequantize_uvg_fx(
Word16 iG1,
Word16 *iG2,
Word16 *G,
Word16 bwidth_fx
,Word16 do_scale
)
{
Word16 i, k;
const Word16 (*UVG1CB)[2]=NULL;
const Word16 (*UVG2CB1)[5]=NULL;
const Word16 (*UVG2CB2)[5]=NULL;
Word16 frac, exp, sc;
Word32 L_tmp;
Word16 Q_gain = 0;
IF( sub(bwidth_fx,NB) == 0 )
{
UVG1CB = UVG1CB_NB_FX;
move16();
UVG2CB1 = UVG2CB1_NB_FX;
move16();
UVG2CB2 = UVG2CB2_NB_FX;
move16();
}
ELSE IF( sub(bwidth_fx,WB) == 0 || sub(bwidth_fx,SWB) == 0)
{
test();
UVG1CB = UVG1CB_WB_FX;
move16();
UVG2CB1 = UVG2CB1_WB_FX;
move16();
UVG2CB2 = UVG2CB2_WB_FX;
move16();
}
IF ( !do_scale)
{
sc = 11;
move16();
}
ELSE
{
test();
IF ( ( sub(UVG1CB[iG1][0], 4096) < 0 ) && ( sub(UVG1CB[iG1][1],4096) < 0 ) ) /* if x < 1, where 10^x is used for gain computation */
{
sc = 8;
move16();
Q_gain = 3;
move16();
}
ELSE
{
sc = 11;
move16();
}
}
FOR (i=0; i<2; i++)
{
FOR (k=0; k<5; k++)
{
IF( i==0 )
{
/* pow(10.0, UVG1CB[iG1][i]) = pow(2.0,UVG1CB[iG1][i]*3.321928 */
L_tmp = L_mult(UVG1CB[iG1][i],27213); /* Q(13+13+1)->Q27 */
L_tmp = L_shr_r(L_tmp,11); /* Q16 */
frac = L_Extract_lc(L_tmp,&exp);
frac = extract_l(Pow2(14,frac));
G[i*5+k] = round_fx(L_shl(L_mult(frac,UVG2CB1[iG2[i]][k]),exp-sc)); /* Q0 */
}
ELSE IF (sub(i,1)==0)
{
L_tmp = L_mult(UVG1CB[iG1][i],27213); /* Q(13+13+1)->Q27 */
L_tmp = L_shr_r(L_tmp,11); /* Q16 */
frac = L_Extract_lc(L_tmp,&exp);
frac = extract_l(Pow2(14,frac));
G[i*5+k] = round_fx(L_shl(L_mult(frac,UVG2CB2[iG2[i]][k]),exp-sc)); /* Q0 */
}
}
}
return Q_gain;
}
/*===================================================================*/
/* FUNCTION : generate_nelp_excitation_fx */
/*-------------------------------------------------------------------*/
/* PURPOSE : This function computes the random
excitation scaled by gain */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16*) Gains : Gain vector (Q_exc) */
/* _ (Word16) gain_fac : gain factor (Q14) */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16*) seed : Random seed (Q0) */
/* _ (Word16*) output : excitation output (Q_exc) */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None. */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None. */
/*===================================================================*/
void generate_nelp_excitation_fx(
Word16 *seed, /* i/o: random number seed */
Word16 *Gains, /* i : excitation gains Q_exc*/
Word16 *output, /* o : excitation output */
Word16 gain_fac /* i : gain factor */
)
{
Word16 i, len, j;
Word16 tmp[31], tmp1[31], tmpf, L16;
Word16 k1, k2, I[31], tmpi;
Word32 L32;
Word16 cnt;
FOR (i=0; i<10; i++)
{
IF (sub(i,9)==0)
{
len=31;
move16();
cnt=8;
move16();
}
ELSE
{
len=25;
move16();
cnt=6;
move16();
}
FOR (j=0; j<len; j++)
{
L32 = L_mult0(*seed,0x0209); /* L32 = *seed*521; */
L16 = extract_l(L_add(L32,259));
*seed = L16;
move16(); /* Q0 */
tmp[j] = *seed;
move16(); /* Q15, tmp[j]=*seed/32768 */
tmp1[j] = abs_s(tmp[j]);
I[j] = j;
move16();
}
j = sub(len,1);
FOR (k1=0; k1<j; k1++)
{
FOR (k2=add(k1,1); k2<len; k2++)
{
IF (sub(tmp1[k2],tmp1[k1])>0)
{
tmpi = I[k2];
move16();
tmpf = tmp1[k2];
move16();
tmp1[k2] = tmp1[k1];
move16();
I[k2] = I[k1];
move16();
tmp1[k1] = tmpf;
move16();
I[k1] = tmpi;
move16();
}
}
}
/*using a factor of 1.37 to compensate for the ~ 2.5 ( or 2.73) dB diff between this scheme and EVS-UV */
FOR (j=0; j<cnt; j++)
{
L16 = mult_r(tmp[I[j]], gain_fac); /* Q14 */
L16 = mult_r(L16, 0x6EDA); /* Q13 */
output[i*25+I[j]]= round_fx(L_shl(L_mult(L16,Gains[i]),2)); /* Q_exc */
}
FOR (; j<len; j++)
{
output[i*25+I[j]] = 0;
move16();
}
}
}
+22
View File
@@ -0,0 +1,22 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef OPTIONS_H
#define OPTIONS_H
#include "stl.h"
/* ################### Start compiler switches ######################## */
/* */
#ifdef _MSC_VER
#pragma warning(disable:4310) /* cast truncates constant value this affects mainly constants tables*/
#endif
#define SUPPORT_JBM_TRACEFILE /* support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */
/* */
/* ##################### End compiler switches ######################## */
#endif /* OPTIONS_H */
+276
View File
@@ -0,0 +1,276 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "stl.h"
#include <assert.h>
#include "prot_fx.h"
/********************************/
/* Helper functions */
/********************************/
/** Put nBits long encoded value from *pStream into bitstream. Using the function EncodeValue for encoding. */
static Word16 PutIntoBitstream(Word16 const ** pStream, TEncodeValue EncodeValue, Word16 index, Encoder_State_fx *st_fx, Word16 nBits)
{
Word16 value;
Word16 codedValue;
move16();
value = *(*pStream)++;
codedValue = EncodeValue(value, index);
push_next_indice_fx(st_fx, codedValue, nBits);
return value;
}
/** Get nBits long value from bitstream into *pStream. */
static Word16 GetFromBitstream(Decoder_State_fx *st, TDecodeValue DecodeValue, Word16 index, Word16 nFixedBits, Word16 ** pStream)
{
Word16 value;
move16();
move16();
value = 0;
IF (DecodeValue != NULL)
{
DecodeValue(st, index, &value);
}
ELSE
{
value = get_next_indice_fx(st, nFixedBits);
}
move16();
*(*pStream)++ = value;
return value;
}
static Word16 FixedWidthEncoding(Word16 value, Word16 index)
{
(void)index;
return value;
}
/********************************/
/* Interface functions */
/********************************/
void GetParameters(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, void const * pParameter, Word16 ** pStream, Word16 * pnSize, Word16 * pnBits)
{
Word16 index;
Word16 iParam, nParams;
Word16 value;
void const * pSubStruct;
assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pParameter != NULL) && (pStream != NULL) && (pnSize != NULL) && (pnBits != NULL));
move16();
nParams = paramsBitMap->nParams;
FOR (index = 0; index < nArrayLength; index++)
{
FOR (iParam = 0; iParam < nParams; iParam++)
{
ParamBitMap const * param;
move16();
param = & paramsBitMap->params[iParam];
pSubStruct = param->GetParamValue(pParameter, index, &value);
/* If a function for encoding/decoding value is defined than it should take care of 0 */
IF ( s_or(param->fZeroAllowed != 0, param->EncodeValue != NULL) )
{
move16();
*(*pStream)++ = value;
}
ELSE
{
move16();
*(*pStream)++ = sub(value, 1);
}
move16();
*pnSize = add(*pnSize, 1);
IF (param->nBits != 0)
{
move16();
*pnBits = add(*pnBits, param->nBits);
}
ELSE
{
move16();
*pnBits = add(*pnBits, param->GetNumberOfBits(value, index));
}
IF ( s_and(param->pSubParamBitMap != NULL, value > 0) )
{
const void *pointer;
move16();
pointer = pParameter;
if (pSubStruct != NULL)
{
move16();
pointer = pSubStruct;
}
GetParameters(param->pSubParamBitMap, value, pointer, pStream, pnSize, pnBits);
}
}
}
}
void SetParameters(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, void * pParameter, Word16 const ** pStream, Word16 * pnSize)
{
Word16 index;
Word16 iParam, nParams;
Word16 value;
void * pSubStruct;
void * pTmp;
assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pParameter != NULL) && (pStream != NULL) && (pnSize != NULL));
nParams = paramsBitMap->nParams;
FOR (index = 0; index < nArrayLength; index++)
{
FOR (iParam = 0; iParam < nParams; iParam++)
{
ParamBitMap const *param;
/* If a function for encoding/decoding value is defined than it should take care of 0 */
move16();
param = &paramsBitMap->params[iParam];
move16();
value = 1;
if ( s_or(param->fZeroAllowed!=0, param->EncodeValue != NULL) )
{
move16();
value = 0;
}
value = add(value, *(*pStream)++);
pSubStruct = param->SetParamValue(pParameter, index, value);
move16();
*pnSize = add(*pnSize, 1);
IF ( s_and(param->pSubParamBitMap != NULL, value > 0) )
{
pTmp = pParameter;
if(pSubStruct != NULL) pTmp = pSubStruct;
SetParameters(param->pSubParamBitMap, value, pTmp, pStream, pnSize);
}
}
}
}
void WriteToBitstream(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, Word16 const ** pStream, Word16 * pnSize, Encoder_State_fx *st, Word16 * pnBits)
{
Word16 index;
Word16 iParam, nParams;
assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pStream != NULL) && (pnSize != NULL) && (st != NULL) && (pnBits != NULL));
nParams = paramsBitMap->nParams;
FOR (index = 0; index < nArrayLength; index++)
{
FOR (iParam = 0; iParam < nParams; iParam++)
{
ParamBitMap const *param;
Word16 nBits;
/* If a function for encoding/decoding value is defined than it should take care of 0 */
Word16 fShiftValue;
TEncodeValue EncodeValue;
Word16 value;
move16();
param = &paramsBitMap->params[iParam];
move16();
nBits = param->nBits;
IF (param->nBits == 0)
{
nBits = param->GetNumberOfBits(**pStream, index);
}
test();
test();
fShiftValue = s_and(param->fZeroAllowed==0, param->EncodeValue == NULL);
move16();
EncodeValue = param->EncodeValue;
if (param->EncodeValue == NULL)
{
move16();
EncodeValue = &FixedWidthEncoding;
}
value = PutIntoBitstream(pStream, EncodeValue, index, st, nBits);
if (fShiftValue)
{
value = add(value, 1);
}
move16();
*pnSize = add(*pnSize, 1);
move16();
*pnBits = add(*pnBits, nBits);
IF ((param->pSubParamBitMap != NULL) && (value > 0))
{
WriteToBitstream(param->pSubParamBitMap, value, pStream, pnSize, st, pnBits);
}
}
}
}
void ReadFromBitstream(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, Decoder_State_fx *st, Word16 ** pStream, Word16 * pnSize)
{
Word16 index;
Word16 iParam, nParams;
Word16 fShiftValue;
Word16 value;
assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pStream != NULL) && (pnSize != NULL) && (st != NULL));
move16();
nParams = paramsBitMap->nParams;
FOR (index = 0; index < nArrayLength; index++)
{
FOR (iParam = 0; iParam < nParams; iParam++)
{
ParamBitMap const * param;
/* If a function for encoding/decoding value is defined than it should take care of 0 */
move16();
param = & paramsBitMap->params[iParam];
test();
test();
fShiftValue = s_and(param->fZeroAllowed==0, param->EncodeValue == NULL);
value = GetFromBitstream(st, param->DecodeValue, index, param->nBits, pStream);
if (fShiftValue)
{
move16();
value = add(value, 1);
}
IF ((param->pSubParamBitMap != NULL) && (value > 0))
{
ReadFromBitstream(param->pSubParamBitMap, value, st, pStream, pnSize);
}
}
}
move16();
*pnSize = add(*pnSize, i_mult(nParams, nArrayLength));
}
+177
View File
@@ -0,0 +1,177 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <assert.h>
#include "options.h" /* EV-VBR compilation switches */
#include "prot_fx.h"
#include "basop_util.h"
#include "stl.h" /* Weighted mops computation related code */
/*-----------------------------------------------------------------------*
* phase_dispersion:
*
* post-processing to enhance noise at low bit rate.
*-----------------------------------------------------------------------*/
void phase_dispersion(
const Word32 gain_code, /* i : gain of code 15Q16 */
const Word16 gain_pit, /* i : gain of pitch Q14 */
Word16 code[], /* i/o: code vector */
Word16 *code_exp, /* i/o: exponent of code */
const Word16 mode, /* i : level, 0=hi, 1=lo, 2=off */
Word32 *prev_gain_code, /* i/o: static memory 15Q16 */
Word16 prev_gain_pit[], /* i/o: static memory Q14, size=6 */
Word16 *prev_state, /* i/o: static memory Q0 */
Word16 L_subfr /* i : subframe length [40,64,80]*/
)
{
Word16 i, j, state, scale2;
Word32 x32[2*L_SUBFR];
Word16 *code_real, *code_imag;
const Word16 *h_real, *h_imag;
move16();
state = 2;
if ( sub(gain_pit,14746/*0.9f Q14*/) < 0)
{
move16();
state = 1;
}
if ( sub(gain_pit, 9830/*0.6f Q14*/) < 0 )
{
move16();
state = 0;
}
FOR (i=5; i>0; i--)
{
move16();
prev_gain_pit[i] = prev_gain_pit[i-1];
}
move16();
prev_gain_pit[0] = gain_pit;
IF ( L_sub(gain_code, L_add(*prev_gain_code, L_shl(*prev_gain_code,1))) > 0 )
{
if (sub(state,2) < 0)
{
state = add(state, 1);
}
}
ELSE
{
j=0;
FOR (i=0; i<6; i++)
{
if ( L_sub(prev_gain_pit[i], 9830/*0.6f Q14*/) < 0 )
{
j = add(j,1);
}
}
if (sub(j,2) > 0)
{
move16();
state = 0;
}
if ( sub(sub(state, *prev_state),1) > 0 )
{
state = sub(state,1);
}
}
move32();
move16();
*prev_gain_code = gain_code;
*prev_state = state;
/*-----------------------------------------------------------------*
* circular convolution
*-----------------------------------------------------------------*/
state = add(state, mode); /* level of dispersion */
j = *code_exp;
move16();
IF( sub(state,2) < 0 )
{
FOR(i=0; i<L_subfr; i++)
{
x32[i] = L_deposit_h(code[i]);
}
BASOP_rfft(x32, L_subfr, &j, -1);
/* Normalize output data. */
scale2 = getScaleFactor32(x32, L_subfr);
FOR (i=0; i<L_subfr/2-1; i++)
{
code[i] = round_fx(L_shl(x32[2*i+0], scale2));
code[L_subfr-1-i] = round_fx(L_shl(x32[2*i+3], scale2));
}
code[L_subfr/2-1] = round_fx(L_shl(x32[L_subfr-2], scale2));
code[L_subfr/2] = round_fx(L_shl(x32[1], scale2));
j = sub(j, scale2);
h_real = low_H16k;
move16();
if( sub(L_subfr, 64) <= 0)
{
h_real = low_H;
move16();
}
IF ( sub(state, 1) == 0)
{
h_real = mid_H16k;
move16();
if( sub(L_subfr, 64) <= 0)
{
h_real = mid_H;
move16();
}
}
h_imag = h_real + L_subfr - 1;
move16();
code_real = &code[0];
code_imag = &code[L_subfr-1];
x32[0] = L_mult(*code_real++, *h_real++);
move32();
FOR (i=1; i<L_subfr/2; i++)
{
x32[2*i] = L_msu(L_mult(*code_real, *h_real) ,*code_imag, *h_imag);
move32();
x32[2*i+1] = L_mac(L_mult(*code_real++, *h_imag--),*code_imag--, *h_real++);
move32();
}
x32[1] = L_mult(*code_real++, *h_real++);
move32();
/* low_H and mid_H are in Q14 format, thus account that here. */
j = add(j,1);
BASOP_rfft(x32, L_subfr, &j, 1);
scale2 = getScaleFactor32(x32, L_subfr);
FOR (i=0; i<L_subfr; i++)
{
code[i] = round_fx(L_shl(x32[i], scale2));
}
j = sub(j, scale2);
}
/* Store exponent of code */
move16();
*code_exp = j;
}
+115
View File
@@ -0,0 +1,115 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h"
#include "cnst_fx.h"
#include "prot_fx.h"
#include "stl.h"
/*===================================================================*/
/* FUNCTION : Interpol_delay_fx () */
/*-------------------------------------------------------------------*/
/* PURPOSE : Interpolate pitch lag for a subframe */
/*-------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16) last_fx: previous frame delay, Q0 */
/* _ (Word16) current_fx: current frame delay, Q0 */
/* _ (Word16) SubNum : subframe number */
/*-------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* */
/* _ (Word16 []) out_fx : 3 Intepolated delays, Q4 */
/*-------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/* _ None */
/*-------------------------------------------------------------------*/
/* RETURN ARGUMENTS : _ None. */
/*===================================================================*/
/* NOTE: this function uses a 5 entry table frac_fx (Q4 unsigned) */
/*===================================================================*/
void Interpol_delay_fx(Word16 *out_fx, Word16 last_fx, Word16 current_fx,
Word16 SubNum, const Word16* frac_fx)
{
Word16 i,temp;
Word32 L_add1,L_add2;
FOR (i=0; i<3; i++)
{
temp= sub(16,frac_fx[SubNum+i]);/* Q4 */
L_add1 = L_shr(L_mult(last_fx,temp),1);/* Q4 */
L_add2 = L_shr(L_mult(current_fx,frac_fx[SubNum+i]),1);/* Q4 */
out_fx[i] = (Word16)L_add(L_add1,L_add2);
move16();/* Q4 */
}
return;
}
/*-------------------------------------------------------------------*
* deemph_lpc()
*
* De-emphasis of LP coefficients
* convolve LPC with [1 -PREEMPH_FAC] to de-emphasise LPC
*--------------------------------------------------------------------*/
void deemph_lpc_fx(
Word16 *p_Aq_curr_fx, /* i : LP coefficients current frame */
Word16 *p_Aq_old_fx, /* i : LP coefficients previous frame */
Word16 *LPC_de_curr_fx, /* o : De-emphasized LP coefficients current frame in Q12 */
Word16 *LPC_de_old_fx, /* o : De-emphasized LP coefficients previous frame in Q12 */
Word16 deemph_old
)
{
Word16 k,temp;
Word16 b_fx[M+2];/* Q12 */
Word16 a_fx[2] = {-22282, 32767};/* Q15 {-PREEMPH_FAC,1.0} */
b_fx[0] = 4096;
move16();/* 1 in Q12 */
FOR(k = 0; k < M; k++)
{
b_fx[k+1] = p_Aq_curr_fx[k];
move16();/* Q12 */
}
b_fx[M+1] = 0;
move16();
FOR(k = 0; k <= M; k++)
{
/* LPC_de_curr[k] = a[0]*b[k] + a[1]*b[k+1]; */
temp = mult(a_fx[0],b_fx[k]);/* Q12 */
LPC_de_curr_fx[k] = add(temp,b_fx[k+1]);
move16();/* Q12 */
}
IF ( sub( deemph_old, 1) == 0)
{
/* ignoring the 1st value which is 1.0 in this case */
b_fx[0] = 4096;
move16();/* 1 in Q12 */
FOR(k = 0; k < M; k++)
{
b_fx[k+1] = p_Aq_old_fx[k+1];
move16();
}
b_fx[M+1] = 0;
move16();
FOR(k = 0; k <= M; k++)
{
/* LPC_de_old[k] = a[0]*b[k] + a[1]*b[k+1]; */
temp = mult(a_fx[0],b_fx[k]);/* Q12 */
LPC_de_old_fx[k] = add(temp,b_fx[k+1]);
move16();/* Q12 */
}
}
return; /* both outputs LPC_de_curr_fx and LPC_de_old_fx are in Q12 */
}
+162
View File
@@ -0,0 +1,162 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Function pred_lt4: *
* ~~~~~~~~~ *
*-------------------------------------------------------------------*
* Compute the result of long term prediction with fractional *
* interpolation of resolution 1/4. *
* *
* On return exc[0..L_subfr-1] contains the interpolated signal *
* (adaptive codebook excitation) *
*-------------------------------------------------------------------*/
void pred_lt4(
const Word16 excI[], /* in : excitation buffer */
Word16 excO[], /* out: excitation buffer */
Word16 T0, /* input : integer pitch lag */
Word16 frac, /* input : fraction of lag */
Word16 L_subfr, /* input : subframe size */
const Word16 *win, /* i : interpolation window */
const Word16 nb_coef, /* i : nb of filter coef */
const Word16 up_sample /* i : up_sample */
)
{
Word16 i, j;
Word32 s;
const Word16 *x0, *x1, *x2, *c1, *c2;
x0 = &excI[-T0];
frac = negate(frac);
IF ( frac < 0 )
{
frac = add(frac,up_sample);
x0--;
}
FOR (j=0; j<L_subfr; j++)
{
x1 = x0++;
x2 = x1+1;
c1 = (&win[frac]);
c2 = (&win[up_sample-frac]);
s = L_deposit_l(0);
FOR(i=0; i<nb_coef; i++)
{
/*s += (*x1--) * (*c1) + (*x2++) * (*c2);*/
s = L_mac0(s, (*x1--),(*c1));
s = L_mac0(s, (*x2++),(*c2));
c1+=up_sample;
c2+=up_sample;
}
#if (INTERP_EXP != -1)
s = L_shl(s,INTERP_EXP+1);
#endif
excO[j] = round_fx(s);
}
return;
}
/*======================================================================*/
/* FUNCTION : pred_lt4_tc_fx() */
/*-----------------------------------------------------------------------*/
/* PURPOSE : * adapt. search of the second impulse in the same subframe (when appears) */
/* On return, exc[0..L_subfr-1] contains the interpolated signal */
/* (adaptive codebook excitation) */
/* */
/*-----------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* _ (Word16 []) exc : excitation buffer Q0 */
/* _ (Word16) L_subfr : subframe size Q0 */
/* _ (Word16 ) T0 : integer pitch lag Q0 */
/* _ (Word16 ) frac : fraction of lag Q0 */
/* _ (Word16 ) imp_pos : glottal impulse position Q0 */
/* _ (Word16 *) win : Interpolation window used Q14 */
/*-----------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* _ (Word16 []) exc : output excitation buffer Q0 */
/*-----------------------------------------------------------------------*/
/* INPUT OUTPUT ARGUMENTS */
/* NONE */
/*-----------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* NONE */
/*=======================================================================*/
void pred_lt4_tc_fx(
Word16 exc[], /* i/o: excitation buffer */
const Word16 T0, /* i : integer pitch lag */
Word16 frac, /* i: fraction of lag */
const Word16 *win, /* i : interpolation window */
const Word16 imp_pos, /* i : glottal impulse position */
const Word16 i_subfr /* i : subframe index */
)
{
Word16 i, j,k,l;
const Word16 *x0;
Word16 excO[L_SUBFR+1];
Word32 L_sum;
Word16 excI[2*L_SUBFR];
Copy( exc + sub(i_subfr, L_SUBFR), excI, shl(L_SUBFR,1) );
test();
IF (sub(add(T0, sub(imp_pos, L_IMPULSE2)), L_SUBFR) < 0 && sub(T0, L_SUBFR) < 0)
{
set16_fx(&excI[sub(L_SUBFR,T0)], 0, T0);
set16_fx(excO, 0, L_SUBFR+1 );
x0 = excI + sub(L_SUBFR, L_INTERPOL2-1);
IF (frac > 0)
{
frac = sub(frac,UP_SAMP);
x0--;
}
l = add(UP_SAMP-1, frac);
FOR (j = T0; j < L_SUBFR+1; j++)
{
k = l;
move16();
L_sum = L_mult(x0[0], win[k]);
FOR (i = 1; i < 2 * L_INTERPOL2; i++)
{
/*
* Here, additions with UP_SAMP are not counted
ki* because, the window could easily be modified
* so that the values needed are contiguous.
*/
k += UP_SAMP;
L_sum = L_mac(L_sum, x0[i], win[k]); /*Q1 */
}
L_sum = L_shl(L_sum, 1); /*Q0h */
excO[j] = round_fx(L_sum);
x0++;
}
FOR (i = T0; i < L_SUBFR; i++)
{
exc[i+i_subfr] = add(exc[i+i_subfr], mult_r(PIT_SHARP_fx, excO[i]));
move16();
}
}
return;
}
+136
View File
@@ -0,0 +1,136 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------*
* preemph_copy_fx()
*
* Preemphasis: filtering through 1 - mu z^-1
*-------------------------------------------------------------*/
void preemph_copy_fx(
const Word16 x[], /* i : input signal Qx */
Word16 y[], /* o : output signal Qx */
const Word16 mu, /* i : preemphasis coefficient Q15 */
const Word16 lg, /* i : vector size Q0 */
Word16 *mem /* i/o: memory (x[-1]) Qx */
)
{
Word16 i, temp;
temp = x[lg - 1];
move16();
FOR (i = sub(lg, 1); i > 0; i--)
{
y[i] = msu_r(L_deposit_h(x[i]), x[i - 1], mu);
move16();
}
y[0] = msu_r(L_deposit_h(x[0]), *mem, mu);
move16();
*mem = temp;
move16();
}
/*
* E_UTIL_f_preemph2
*
* Parameters:
* shift I: scale output
* signal I/O: signal Qx/Qx+shift
* mu I: preemphasis factor Q15
* L I: vector size
* mem I/O: memory (x[-1])
*
* Function:
* Filtering through 1 - mu z^-1
*
* Returns:
* void
*/
void E_UTIL_f_preemph2(Word16 shift, Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem)
{
Word16 i, temp;
Word32 L_tmp;
temp = signal[lg - 1];
move16();
FOR (i = sub(lg, 1); i > 0; i--)
{
L_tmp = L_mult(signal[i], 16384);
L_tmp = L_msu0(L_tmp, signal[i - 1], mu);
L_tmp = L_shl(L_tmp, add(shift,1));
signal[i] = round_fx(L_tmp);
}
L_tmp = L_mult(signal[0], 16384);
L_tmp = L_msu0(L_tmp, *mem, mu);
L_tmp = L_shl(L_tmp, add(shift,1));
signal[0] = round_fx(L_tmp);
*mem = temp;
move16();
return;
}
Word16 E_UTIL_f_preemph3(Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem, Word16 bits)
{
Word16 i, QVal, mus, tmp_fixed, Q_new;
Word32 L_tmp, L_maxloc;
QVal = shl(1, sub(15,bits));
mus = shr(mu, bits);
L_tmp = L_mult(signal[0], QVal);
L_tmp = L_msu(L_tmp, *mem, mus);
L_maxloc = L_abs(L_tmp);
FOR (i = 1; i < lg; i++)
{
L_tmp = L_mult(signal[i], QVal);
L_tmp = L_msu(L_tmp, signal[i - 1], mus);
L_tmp = L_abs(L_tmp);
L_maxloc = L_max(L_tmp, L_maxloc);
}
tmp_fixed = extract_h(L_maxloc);
Q_new = Q_MAX;
move16();
IF (tmp_fixed != 0)
{
Q_new = sub(norm_s(tmp_fixed), bits);
Q_new = s_max(Q_new, 0);
Q_new = s_min(Q_new, Q_MAX);
}
tmp_fixed = signal[lg - 1];
move16();
FOR (i = sub(lg,1); i > 0; i--)
{
L_tmp = L_mult(signal[i], QVal);
L_tmp = L_msu(L_tmp, signal[i - 1], mus);
L_tmp = L_shl(L_tmp, Q_new);
signal[i] = round_fx(L_tmp);
}
L_tmp = L_mult(signal[0], QVal);
L_tmp = L_msu(L_tmp, *mem, mus);
L_tmp = L_shl(L_tmp, Q_new);
signal[0] = round_fx(L_tmp);
*mem = tmp_fixed;
move16();
return Q_new;
}
+11078
View File
File diff suppressed because it is too large Load Diff
+753
View File
@@ -0,0 +1,753 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "stl.h" /* required for wmc_tool */
#include "options.h"
UWord32 intLimCDivPos_fx(
UWord32 NUM,
Word16 DEN
)
{
UWord32 UL_ru, UL_rl;
Mpy_32_32_uu(UL_lshl(NUM, 1), intLimCDivInvDQ31[DEN], &UL_ru, &UL_rl);
return UL_ru;
}
Word32 intLimCDivSigned_fx(
Word32 NUM,
Word16 DEN)
{
Word32 L_tmp;
L_tmp = intLimCDivPos_fx( L_abs(NUM) , DEN);
if (NUM < 0)
{
L_tmp= L_negate(L_tmp); /* one op */
}
return L_tmp;
}
Word16 shrtCDivSignedApprox( const Word16 num,
const Word16 den
)
{
Word16 pool_part;
pool_part = extract_h( L_mult( negate(abs_s(num)), lim_neg_inv_tbl_fx[den] ));
/* neg_in always, positive out always, so that positive truncation(rounding) is used */
if ( num < 0 )
{
pool_part = negate(pool_part); /* make negative, one op */
}
return pool_part;
}
void nearProjQ15_fx(
Word16 x,
Word16 *result
)
{
const Word16 a[4] = {14967, -25518, 3415, 32351};
Word32 b;
UWord16 lsb;
b = L_deposit_l(a[0]);
b = L_shl((Word32)add(a[1], extract_h(L_mult0((Word16)b, x))), 1);
Mpy_32_16_ss(b, x, &b, &lsb);
b = L_add((Word32)a[2], b);
Mpy_32_16_ss(b, x, &b, &lsb);
b = L_add((Word32)a[3], b);
*result = extract_l(b);
return ;
}
/*-------------------------------------------------------------------*
* obtainEnergyQuantizerDensity_fx()
*
*
*-------------------------------------------------------------------*/
void obtainEnergyQuantizerDensity_fx(
const Word16 L,
const Word16 R,
Word16 *Density )
{
Word16 Rnrg, den, n;
den = sub(shl(L, 1), 1);
IF( den <= 67 )
{
Rnrg = extract_l(intLimCDivPos_fx( L_deposit_l(R) , den));
}
ELSE
{
n = norm_s(den);
Rnrg = shr(div_s(R, shl(den, n)), sub(15, n));
}
Rnrg = add(Rnrg, 28);
Rnrg = s_min(Rnrg, 56);
Rnrg = s_min(Rnrg, sub(R, 96));
Rnrg = s_max(Rnrg, 3);
*Density = obtainEnergyQuantizerDensity_f[Rnrg];
return;
}
/*-------------------------------------------------------------------*
* dsDirac2Dirac_fx()
*
*
*-------------------------------------------------------------------*/
void dsDirac2Dirac_fx(
const Word16 dsDiracIndex,
Word16 *diracs
)
{
*diracs = dsDiracsTab[dsDiracIndex];
return;
}
void dsDiracPerQuanta_fx(
const Word16 td,
const Word16 t_quanta,
const Word16 dsm,
const unsigned char* const *frQuanta,
Word16 *DsIdx
)
{
const unsigned char *sv;
Word16 nsv;
Word16 t_quanta_o;
Word16 dsIndex;
Word16 i;
sv = frQuanta[td];
nsv = sv[0];
t_quanta_o = sub(t_quanta, QUANTAQ3OFFSET);
IF (sub(t_quanta_o, sv[nsv]) >= 0)
{
*DsIdx = nsv;
move16();
return ;
}
IF (sub(t_quanta_o, sv[1]) <= 0)
{
*DsIdx = 1;
move16();
return ;
}
dsIndex = shl(1, frQuanta[0][td]);
if (sub(t_quanta_o, sv[shr(nsv, 1) ]) > 0 )
{
dsIndex = sub(nsv, dsIndex );
}
FOR (i = sub(frQuanta[0][td], 1); i >= 0; i--)
{
dsIndex = add(dsIndex, shl(sub(shl(lshr(sub(sv[dsIndex], t_quanta_o), 15), 1), 1), i));
}
dsIndex = add(dsIndex, lshr(sub(sv[dsIndex], t_quanta_o), 15));
dsIndex = sub(dsIndex, lshr(sub(1, dsIndex), 15));
IF (dsm > 0)
{
*DsIdx=dsIndex;
move16();
return;
}
*DsIdx = add(dsIndex, lshr(sub(add(sv[add(dsIndex,1)], sv[dsIndex]), shl(t_quanta_o, 1)), 15));
return;
}
void QuantaPerDsDirac_fx(
Word16 td,
Word16 dsDiracIndex,
const unsigned char* const* dimFrQuanta,
Word16 *Quanta
)
{
*Quanta = dimFrQuanta[td][dsDiracIndex];
move16();
if(dsDiracIndex == 0)
{
*Quanta = -1; /* single op */ move16();
}
*Quanta = add(*Quanta, QUANTAQ3OFFSET);
return ;
}
void conservativeL1Norm_fx(
Word16 L,
Word16 Qvec,
Word16 Fcons,
Word16 Qavail,
Word16 Qreserv,
Word16 Dspec,
Word16 *Dvec,
Word16 *Qspare,
Word16 *Qreservplus,
Word16 *Dspecplus
)
{
Word16 Minit, Mprime;
Word16 Qtestminus;
const unsigned char *frQuantaL;
frQuantaL = hBitsN[L];
*Qreservplus = add(Qreserv, sub(Qvec, QUANTAQ3OFFSET));
dsDiracPerQuanta_fx(L, Qvec, Fcons, hBitsN, &Minit);
Mprime = Minit;
move16();
DO
{
Qtestminus = (short)frQuantaL[Mprime];
move16();
*Qspare = sub(Qavail, Qtestminus);
Mprime = sub(Mprime, 1);
}
WHILE ( (Mprime >= 0) && sub(*Qspare, QUANTAQ3OFFSET ) < 0 );
if(Mprime < 0)
{
*Qspare = add(Qavail, QUANTAQ3OFFSET); /* single op */
}
dsDirac2Dirac_fx(add(Mprime, 1), Dvec);
*Dspecplus = add(Dspec, *Dvec);
*Qreservplus = sub(*Qreservplus, (short)frQuantaL[Minit]);
*Qspare = sub(*Qspare, QUANTAQ3OFFSET);
return;
}
void bandBitsAdjustment_fx(
Word16 Brc,
UWord32 INTrc,
Word16 Bavail,
Word16 Nbands,
Word16 D,
Word16 L,
Word16 Bband,
Word16 Breserv,
Word16 *Bband_adj,
Word16 *Brem,
Word16 *Breservplus)
{
Word16 Btemp;
Word16 Bff;
Word32 L_tmp;
rangeCoderFinalizationFBits_fx(Brc, INTrc, &Bff);
IF(sub(D, Nbands) < 0)
{
L_tmp = L_deposit_l(sub(Breserv, Bff));
Btemp = extract_l(intLimCDivSigned_fx(L_tmp, s_min(D, 3))); /* result always fits in Word16 */
*Breservplus = add(Bband, Breserv);
}
ELSE
{
Btemp = 0;
move16();
*Breservplus = add(Bband, Bff);
}
*Bband_adj = s_min(extract_l(L_mult(L, 40)), Bband);
*Brem = sub(Bavail, Bff);
*Bband_adj = s_min(*Brem, add(*Bband_adj, Btemp));
*Bband_adj = s_max(0, *Bband_adj);
}
static Word16 Ratio_base2Q11_fx( /* o : Q11 */
const Word16 opp, /* i : Q15 */
const Word16 near /* i : Q15 */
)
{
Word16 mc, nc, ms, ns, d, z;
Word16 result;
Word32 acc;
ns = norm_s(opp ); /* exponent */
nc = norm_s(near ); /* exponent */
ms = shl(opp, ns); /* mantissa */
mc = shl(near, nc); /* mantissa */
acc = L_mac(538500224L, mc, -2776); /* a0*mc + a1, acc(Q27), a0(Q11), a1(Q27) */
z = mac_r(acc, ms, -2776); /* z in Q11, a0 in Q11 */
d = sub(ms, mc); /* d in Q15 */
z = mult_r(z, d); /* z in Q11 */
result = add(z, shl(sub(nc, ns), 11));
return result;
}
void Ratio_rQ3_fx(
Word16 opp,
Word16 near,
Word16 *result
)
{
Word16 tmp;
tmp = add(1<<7 , Ratio_base2Q11_fx(opp, near));
*result = shr(tmp, 8);
return ;
}
void densityAngle2RmsProjDec_fx(
Word16 D,
Word16 indexphi,
Word16 *oppQ15,
Word16 *nearQ15,
Word16 *oppRatioQ3
)
{
Word16 phiQ14q;
Word16 oppTail, nearTail;
phiQ14q = (Word16)intLimCDivPos_fx(L_shl(L_deposit_l(indexphi), 13), shr(D, 1));
if (indexphi < 0)
{
phiQ14q = 1 << 13; /* one op */ move16();
}
oppTail = shr(sub(16320, phiQ14q), 15);
nearTail = shr(sub(phiQ14q, 64), 15);
IF (s_or(oppTail, nearTail) < 0)
{
*oppQ15 = s_and(oppTail, (1 << 15) - 1);
*nearQ15 = s_and(nearTail, (1 << 15) - 1);
*oppRatioQ3 = shl(add(1, shl(nearTail, 1)), 14);
}
ELSE
{
nearProjQ15_fx( shl(sub(1 << 14, phiQ14q), 1), oppQ15);
nearProjQ15_fx(shl(phiQ14q, 1), nearQ15);
Ratio_rQ3_fx(*oppQ15, *nearQ15, oppRatioQ3);
}
return;
}
void densityAngle2RmsProjEnc_fx(
Word16 D,
Word16 phiQ14uq,
Word16 *indexphi,
Word16 *oppQ15,
Word16 *nearQ15,
Word16 *oppRatioQ3
)
{
*indexphi = mult_r(shl(D, 1), phiQ14uq);
if (s_and(D, 1) > 0)
{
*indexphi = -1; /* one op */ move16();
}
densityAngle2RmsProjDec_fx(D, *indexphi, oppQ15, nearQ15, oppRatioQ3);
return;
}
void NearOppSplitAdjustment_fx(
const Word16 qband,
const Word16 qzero,
const Word16 Qac,
const UWord32 INTac,
const Word16 qglobal,
const Word16 FlagCons,
const Word16 Np,
const Word16 Nhead,
const Word16 Ntail,
const Word16 Nnear,
const Word16 Nopp,
Word16 oppRQ3,
Word16 *qnear,
Word16 *qopp,
Word16 *qglobalupd
)
{
Word16 qac, qboth, qskew, qavg, qmin, Midx;
Word32 L_QIb, L_qnum;
Word16 QIb, QIa;
rangeCoderFinalizationFBits_fx(Qac, INTac, &qac);
qboth = sub(qband, sub(qac, qzero));
/* skew calc code */
qskew = 0 ;
move16();
IF (sub(Nhead, 1) > 0)
{
qavg = extract_h(L_shl(intLimCDivSigned_fx((Word32)qboth, Np),16)); /* qboth may be negative */
dsDiracPerQuanta_fx(Ntail, qavg, FlagCons, hBitsN, &Midx );
QuantaPerDsDirac_fx(Nhead, Midx, hBitsN, &qmin);
qskew = sub(qavg, qmin);
qskew = s_max(0, qskew);
} /* end of skew calc code*/
QIa = add(extract_l(intLimCDivPos_fx((UWord32)L_deposit_l(Nopp), Nnear)), 1); /* always positive Word16 out */
L_qnum = L_sub( L_deposit_l(sub(sub(add(qband, qzero), qac), qskew)), L_mult0(Nopp, oppRQ3));
L_QIb = L_deposit_l(0);
IF (L_qnum > 0)
{
L_QIb = (Word32) intLimCDivPos_fx(L_qnum, QIa);
}
*qnear = qboth;
QIb = extract_h(L_shl(L_QIb, 16)); /* may saturate */
if (sub(QIb, qboth) <= 0)
{
*qnear = QIb;
}
*qopp = sub(qboth, *qnear);
*qglobalupd = sub(qglobal, sub(qac, qzero));
return;
}
/*--------------------------------------------------------------------------*
* apply_gain()
*
* Apply gain
*--------------------------------------------------------------------------*/
void apply_gain_fx(
const Word16 *ord, /* i : Indices for energy order */
const Word16 *band_start, /* i : Sub band start indices */
const Word16 *band_end, /* i : Sub band end indices */
const Word16 num_sfm, /* i : Number of bands */
const Word16 *gains, /* i : Band gain vector Q12 */
Word16 *xq /* i/o: Float synthesis / Gain adjusted synth Q15/Q12 */
)
{
Word16 band,i;
Word16 g; /* Q12 */
FOR ( band = 0; band < num_sfm; band++)
{
g = gains[ord[band]];
FOR( i = band_start[band]; i < band_end[band]; i++)
{
/*xq[i] *= g; */
xq[i] = mult_r(g, xq[i]);
move16(); /*12+15+1-16=12 */
}
}
return;
}
/*--------------------------------------------------------------------------*
* fine_gain_quant()
*
* Fine gain quantization
*--------------------------------------------------------------------------*/
void fine_gain_quant_fx(
Encoder_State_fx *st_fx,
const Word16 *ord, /* i : Indices for energy order */
const Word16 num_sfm, /* i : Number of bands */
const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */
Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */
const Word16 *gopt /* i : Optimal gains Q12 */
)
{
Word16 band;
Word16 gbits;
Word16 idx;
Word16 gain_db,gain_dbq;
Word16 err;
Word16 tmp1, tmp2, exp1, exp2;
Word32 L_tmp;
UWord16 lsb;
FOR ( band = 0; band < num_sfm; band++)
{
gbits = gain_bits[ord[band]];
test();
IF ( fg_pred[band] != 0 && gbits > 0 )
{
exp1 = norm_s(gopt[band]);
exp1 = sub(exp1, 1);
tmp1 = shl(gopt[band], exp1);
exp2 = norm_s(fg_pred[band]);
tmp2 = shl(fg_pred[band], exp2);
exp1 = add(15, sub(exp1, exp2));
err = div_s(tmp1, tmp2);
tmp1 = norm_s(err);
exp2 = Log2_norm_lc(L_deposit_h(shl(err, tmp1)));
tmp1 = sub(14, tmp1);
tmp1 = sub(tmp1, exp1);
L_tmp = L_Comp(tmp1, exp2);
Mpy_32_16_ss(L_tmp, 24660, &L_tmp, &lsb); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */
gain_db = round_fx(L_shl(L_tmp, 17));
idx = squant_fx(gain_db, &gain_dbq, finegain_fx[gbits-1], gain_cb_size[gbits-1]);
push_indice_fx( st_fx, IND_PVQ_FINE_GAIN, idx, gbits );
L_tmp = L_mult0(gain_dbq, 21771); /* 21771=0.05*log2(10) */ /* 14+17=31 */
L_tmp = L_shr(L_tmp, 15);
tmp1 = L_Extract_lc(L_tmp, &exp1);
tmp1 = abs_s(tmp1);
tmp1 = extract_l(Pow2(14, tmp1));
exp1 = sub(14, exp1);
L_tmp = L_mult0(fg_pred[band], tmp1); /*12+exp1 */
fg_pred[band] = round_fx(L_shl(L_tmp, sub(16, exp1))); /*12+exp1+16-exp1-16=12 */
}
}
return;
}
/*-------------------------------------------------------------------*
* srt_vec_ind()
*
* sort vector and save sorting indeces
*-------------------------------------------------------------------*/
void srt_vec_ind16_fx (
const Word16 *linear, /* linear input */
Word16 *srt, /* sorted output*/
Word16 *I, /* index for sorted output */
Word16 length
)
{
Word16 pos,npos;
Word16 idxMem;
Word16 valMem;
/*initilize */
FOR (pos = 0; pos < length; pos++)
{
I[pos] = pos;
move16();
}
Copy(linear, srt,length);
/* now iterate */
FOR (pos = 0; pos < (length - 1); pos++)
{
FOR (npos = (pos + 1); npos < length; npos++)
{
IF (sub(srt[npos], srt[pos]) < 0)
{
idxMem = I[pos];
move16();
I[pos] = I[npos];
move16();
I[npos] = idxMem;
move16();
valMem = srt[pos];
move16();
srt[pos] = srt[npos];
move16();
srt[npos] = valMem;
move16();
}
}
}
return;
}
/*-----------------------------------------------------------------------------
* atan2_fx():
*
* Approximates arctan piecewise with various 4th to 5th order least square fit
* polynomials for input in 5 segments:
* - 0.0 to 1.0
* - 1.0 to 2.0
* - 2.0 to 4.0
* - 4.0 to 8.0
* - 8.0 to infinity
*---------------------------------------------------------------------------*/
Word16 atan2_fx( /* o: Angle between 0 and PI/2 radian (Q14) */
const Word32 y, /* i: Argument must be positive (Q15) */
const Word32 x /* i: Q15 */
)
{
Word32 acc, arg;
Word16 man, expo, reciprocal;
Word16 angle, w, z;
IF (x == 0)
{
return 25736; /* PI/2 in Q14 */
}
man = ratio(y, x, &expo); /* man in Q14 */
expo = sub(expo, (15 - 14)); /* Now, man is considered in Q15 */
arg = L_shr((Word32)man, expo);
IF (L_shr(arg, 3+15) != 0)
/*===============================*
* 8.0 <= x < infinity *
*===============================*/
{
/* atan(x) = PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ...
* ~ PI/2 - 1/x, for x >= 8.
*/
expo = norm_l(arg);
man = extract_h(L_shl(arg, expo));
reciprocal = div_s(0x3fff, man);
expo = sub(15 + 1, expo);
reciprocal = shr(reciprocal, expo); /* Q14 */
angle = sub(25736, reciprocal); /* Q14 (PI/2 - 1/x) */
/* For 8.0 <= x < 10.0, 1/(5x^5) is not completely negligible.
* For more accurate result, add very small correction term.
*/
if (L_sub(L_shr(arg, 15), 10L) < 0)
{
angle = add(angle, 8); /* Add tiny correction term. */
}
}
ELSE IF (L_shr(arg, 2+15) != 0)
/*==========================*
* 4.0 <= x < 8.0 *
*==========================*/
{
/* interval: [3.999, 8.001]
* atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4
* = (((a0*8*y + a1)*8*y + a2)*8*y + a3)*8*y + a4 Substitute 8*y -> x
* = (((a0*8^3*y + a1*8^2)*y + a2*8)*y + a3)*8*y + a4
* = ((( c0*y + c1)*y + c2)*y + c3)*8*y + c4,
* where y = x/8
* and a0 = -1.28820869667651e-04, a1 = 3.88263533346295e-03,
* a2 = -4.64216306484597e-02, a3 = 2.75986060068931e-01,
* a4 = 7.49208077809799e-01.
*/
w = extract_l(L_shr(arg, 3)); /* Q15 y = x/8 */
acc = L_add(533625337L, 0); /* Q31 c1 = a1*8^2 */
z = mac_r(acc, w, -2161); /* Q15 c0 = a0*8^3 */
acc = L_add(-797517542L, 0); /* Q31 c2 = a2*8 */
z = mac_r(acc, w, z); /* Q15 */
acc = L_add(592675551L, 0); /* Q31 c3 = a3 */
z = mac_r(acc, w, z); /* z (in:Q15, out:Q12) */
acc = L_add(201114012L, 0); /* Q28 c4 = a4 */
acc = L_mac(acc, w, z); /* Q28 */
angle = extract_l(L_shr(acc, (28 - 14))); /* Q14 result of atan(x), where 4 <= x < 8 */
}
ELSE IF (L_shr(arg, 1+15) != 0)
/*==========================*
* 2.0 <= x < 4.0 *
*==========================*/
{
/* interval: [1.999, 4.001]
* atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4
* = (((a0*4*y + a1)*4*y + a2)*4*y + a3)*4*y + a4 Substitute 4*y -> x
* = (((a0*16*y + a1*4)*y + a2)*4*y + a3)*4*y + a4
* = (((a0*32*y + a1*8)*y + a2*2)*2*y + a3)*4*y + a4
* = ((( c0*y + c1)*y + c2)*2*y + c3)*4*y + c4,
* where y = x/4
* and a0 = -0.00262378195660943, a1 = 0.04089687039888652,
* a2 = -0.25631148958325911, a3 = 0.81685854627399479,
* a4 = 0.21358070563097167
* */
w = extract_l(L_shr(arg, 2)); /* Q15 y = x/4 */
acc = L_add(702602883L, 0); /* Q31 c1 = a1*8 */
z = mac_r(acc, w, -2751); /* Q15 c0 = a0*32 */
acc = L_add(-1100849465L, 0); /* Q31 c2 = a2*2 */
z = mac_r(acc, w, z); /* z (in:Q15, out:Q14) */
acc = L_add(877095185L, 0); /* Q30 c3 = a3 */
z = mac_r(acc, w, z); /* z (in:Q14, out:Q12) */
acc = L_add(57332634L, 0); /* Q28 c4 = a4 */
acc = L_mac(acc, w, z); /* Q28 */
angle = extract_l(L_shr(acc, (28 - 14))); /* Q14 result of atan(x) where 2 <= x < 4 */
}
ELSE IF (L_shr(arg, 15) != 0)
/*==========================*
* 1.0 <= x < 2.0 *
*==========================*/
{
/* interval: [0.999, 2.001]
* atan(x) ~ (((a0*x + 1)*x + a2)*x + a3)*x + a4
* = (((a0*2*y + a1)*2*y + a2)*2*y + a3)*2*y + a4 Substitute 2*y -> x
* = (((a0*4*y + a1*2)*y + a2)*2*y + a3)*2*y + a4
* = (((a0*4*y + a1*2)*y + a2)*y + a3/2)*4*y + a4
* = ((( c0*y + c1)*y + c2)*y + c3)*4*y + c4,
* where y = x/2
* and a0 = -0.0160706457245251, a1 = 0.1527106504065224,
* a2 = -0.6123208404800871, a3 = 1.3307896976322915,
* a4 = -0.0697089375247448
*/
w = extract_l(L_shr(arg, 1)); /* Q15 y= x/2 */
acc = L_add(655887249L, 0); /* Q31 c1 = a1*2 */
z = mac_r(acc, w, -2106); /* Q15 c0 = a0*4 */
acc = L_add(-1314948992L, 0); /* Q31 c2 = a2 */
z = mac_r(acc, w, z);
acc = L_add(1428924557L, 0); /* Q31 c3 = a3/2 */
z = mac_r(acc, w, z); /* z (in:Q15, out:Q13) */
acc = L_add(-37424701L, 0); /* Q29 c4 = a4 */
acc = L_mac(acc, w, z); /* Q29 */
angle = extract_l(L_shr(acc, (29 - 14))); /* Q14 result of atan(x) where 1 <= x < 2 */
}
ELSE
/*==========================*
* 0.0 <= x < 1.0 *
*==========================*/
{
/* interval: [-0.001, 1.001]
* atan(x) ~ ((((a0*x + a1)*x + a2)*x + a3)*x + a4)*x + a5
* = ((((a0*2*x + a1*2)*x/2 + a2)*x + a3)*x + a4)*x + a5
* = (((( c0*x + c1)*x/2 + c2)*x + c3)*x + c4)*x + c5
* where
* a0 = -5.41182677118661e-02, a1 = 2.76690449232515e-01,
* a2 = -4.63358392562492e-01, a3 = 2.87188466598566e-02,
* a4 = 9.97438122814383e-01, a5 = 5.36158556179092e-05.
*/
w = extract_l(arg); /* Q15 */
acc = L_add(1188376431L, 0); /* Q31 c1 = a1*2 */
z = mac_r(acc, w, -3547); /* Q15 c0 = a0*2 */
acc = L_add(-995054571L, 0); /* Q31 c2 = a2 */
z = extract_h(L_mac0(acc, w, z)); /* Q15 non-fractional mode multiply */
acc = L_add(61673254L, 0); /* Q31 c3 = a3 */
z = mac_r(acc, w, z);
acc = L_add(2141982059L, 0); /* Q31 c4 = a4 */
z = mac_r(acc, w, z);
acc = L_add(115139L, 0); /* Q31 c5 = a5 */
acc = L_mac(acc, w, z); /* Q31 */
angle = extract_l(L_shr(acc, 31 - 14)); /* Q14 result of atan(x), where 0 <= x < 1 */
}
return angle; /* Q14 between 0 and PI/2 radian. */
}
+62
View File
@@ -0,0 +1,62 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include <stdlib.h>
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
/*-------------------------------------------------------------------*
* rc_get_bits2()
*
* Get number of bits needed to finalize range coder
*-------------------------------------------------------------------*/
Word16 rc_get_bits2_fx( /* o: Number of bits needed */
const Word16 N, /* i: Number of bits currently used */
const UWord32 range /* i: Range of range coder */
)
{
return add(add(N, 2), norm_ul(range));
}
void rangeCoderFinalizationFBits_fx(
Word16 Brc,
UWord32 INTrc,
Word16 *FBits
)
{
Word32 L_Bq15;
UWord32 h, UL_tmp;
UWord16 Bq15ui16, l;
Word16 B, E, x, k;
*FBits = shl(add(Brc, 32), 3);
B = sub(30, norm_ul(INTrc));
x = sub(B, RCF_INIT_SHIFT );
L_Bq15 = 0;
move16();
if (x >= 0)
{
L_Bq15 = (Word32)UL_lshr(INTrc, x);
}
E = 2;
move16();
FOR(k = 1; k < 4; k++)
{
Bq15ui16 = u_extract_l(L_shr(L_Bq15, s_and(E, 1)));
UL_tmp = UL_lshl(UL_deposit_l(Bq15ui16), 1);
Mpy_32_16_uu(UL_tmp, Bq15ui16, &h , &l);
L_Bq15 = (Word32) h;
E = add(shl(B, 1), extract_l(L_lshr(L_sub(((1L << 16) - 1L), L_Bq15), 31)));
B = E;
move16();
}
*FBits = sub(*FBits, B);
return;
}
+193
View File
@@ -0,0 +1,193 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Prototypes
*-------------------------------------------------------------------*/
static void nearest_neighbor_2D8_fx( const Word32 x[], Word16 y[] );
static Word32 compute_error_2D8_fx( const Word32 x[], const Word16 y[] );
/*--------------------------------------------------------------*
* RE8_PPV:
*
* NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8
* the algorithm is based on the definition of RE8 as
* RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1])
* it applies the coset decoding of Sloane and Conway
* --------------------------------------------------------------*/
void re8_PPV_fx(
const Word32 x[], /* i : point in R^8Q15 */
Word16 y[] /* o : point in RE8 (8-dimensional integer vector) */
)
{
Word16 i, y0[8];
Word32 e0, e1, x1[8];
/*--------------------------------------------------------------*
* find the nearest neighbor y0 of x in 2D8
*--------------------------------------------------------------*/
nearest_neighbor_2D8_fx( x, y0 );
/*--------------------------------------------------------------*
* find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding)
*--------------------------------------------------------------*/
FOR( i=0; i<8; i++ )
{
x1[i] = L_sub(x[i], QR);
move32();
}
nearest_neighbor_2D8_fx( x1, y );
FOR ( i = 0; i < 8; i++ )
{
y[i] = add(y[i], 1);
move16();
}
/*--------------------------------------------------------------*
* compute e0=||x-y0||^2 and e1=||x-y1||^2
*--------------------------------------------------------------*/
e0 = compute_error_2D8_fx( x, y0 );
e1 = compute_error_2D8_fx( x, y );
/*--------------------------------------------------------------*
* select best candidate y0 or y1 to minimize distortion
*--------------------------------------------------------------*/
IF( L_sub(e0, e1) < 0 )
{
Copy( y0, y, 8 );
}
return;
}
/*--------------------------------------------------------------*
* Nearest_neighbor_2D8(x,y)
*
* NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE 2D8
* algorithm: nn_2D8(x) = 2*nn_D8(x/2)
* nn_D8 = decoding of Z^8 with Wagner rule
* (see Conway and Sloane's paper in IT-82)
--------------------------------------------------------------*/
static void nearest_neighbor_2D8_fx(
const Word32 x[], /* i : point in R^8 */
Word16 y[] /* o : point in 2D8 (8-dimensional integer vector) */
)
{
Word16 i,j;
Word16 sum, tmp16, tmp16b;
Word32 s, e, em;
/*--------------------------------------------------------------*
* round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2]
* where [.] is the nearest integer operator
* in the mean time, compute sum = y1+...+y8
*--------------------------------------------------------------*/
sum = 0;
move16();
FOR( i=0; i<8; i++ )
{
/* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */
tmp16 = round_fx(L_add(x[i], L_shr(x[i], 31)));
y[i] = shl(tmp16, 1);
move16();
/* sum += y[i] */
sum = add(sum, y[i]);
}
/*--------------------------------------------------------------*
* check if y1+...+y8 is a multiple of 4
* if not, y is not round xj in the wrong way where j is defined by
* j = arg max_i | xi -yi|
* (this is called the Wagner rule)
*--------------------------------------------------------------*/
IF( s_and(sum, 2) != 0 )
{
/* find j = arg max_i | xi -yi| */
em = L_deposit_l(0);
j = 0;
move16();
FOR( i=0; i<8; i++ )
{
/* compute ei = xi-yi */
/* e[i]=x[i]-y[i] */
e = L_msu(x[i], y[i], QR/2);
/* compute |ei| = | xi-yi | */
s = L_abs(e);
/* check if |ei| is maximal, if so, set j=i */
if( L_sub(em, s) < 0 )
{
j = i;
move16();
}
em = L_max(s, em);
}
/* round xj in the "wrong way" */
e = L_msu(x[j], y[j], QR/2);
tmp16 = extract_h(e);
tmp16b = add(y[j], 2);
if( tmp16 < 0 )
{
tmp16b = sub(tmp16b, 2+2);
}
y[j] = tmp16b;
move16();
}
return;
}
/*--------------------------------------------------------------*
* Compute_error_2D8(x,y)
*
* Compute mean square error between input vector and
* (quantized) point in 2D8.
--------------------------------------------------------------*/
static Word32 compute_error_2D8_fx( /* o : mean squared error */
const Word32 x[], /* i : input vector */
const Word16 y[] /* i : point in 2D8 (8-dimensional integer vector) */
)
{
Word16 i, hi, lo;
Word32 err, Ltmp;
err = L_deposit_l(0);
FOR( i=0; i<8; i++ )
{
/*tmp = x[i]-y[i];*/
Ltmp = L_msu(x[i], y[i], 16384);
hi = extract_h(L_shl(Ltmp, 1));
lo = extract_l(L_msu(Ltmp, hi, 16384));
Ltmp = L_mult(hi, hi);
Ltmp = L_shl(Ltmp, 14);
Ltmp = L_mac(Ltmp, hi, lo);
Ltmp = L_mac0(Ltmp, mult(lo, lo), 1);
/* err+=tmp*tmp */
err = L_add(Ltmp, err);
}
return( err );
}
+387
View File
@@ -0,0 +1,387 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*-------------------------------------------------------------------*
* Prototypes
*-------------------------------------------------------------------*/
static Word16 re8_identify_absolute_leader_fx( const Word16 y[] );
static void re8_coord_fx( const Word16 *y, Word16 *k) ;
/*----------------------------------------------------------------*
* re8_vor_fx()
*
* MULTI-RATE RE8 INDEXING BY VORONOI EXTENSION
*----------------------------------------------------------------*/
void re8_vor_fx(
const Word16 y[], /* i : point in RE8 (8-dimensional integer vector) */
Word16 *n, /* o : codebook number n=0,2,3,4,... (scalar integer) */
Word16 k[], /* o : Voronoi index (integer vector of dimension 8) used only if n>4*/
Word16 c[], /* o : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c */
Word16 *ka /* o : identifier of absolute leader (to index c) */
)
{
Word16 i, r, iter, ka_tmp, n_tmp, mask;
Word16 k_tmp[8], v[8], c_tmp[8], k_mod[8];
Word32 Ltmp, Lsphere;
/*----------------------------------------------------------------*
* verify if y is in Q0, Q2, Q3 or Q4
* (a fast search is used here:
* the codebooks Q0, Q2, Q3 or Q4 are specified in terms of RE8 absolute leaders
* (see FORinstance Xie and Adoul's paper in ICASSP 96)
* - a unique code identifying the absolute leader related to y is computed
* in re8_identify_absolute_leader()
* this code is searched FORin a pre-defined list which specifies Q0, Q2, Q3 or Q4)
* the absolute leader is identified by ka
* - a translation table maps ka to the codebook number n)
*----------------------------------------------------------------*/
*ka = re8_identify_absolute_leader_fx( y );
move16();
/*----------------------------------------------------------------*
* compute codebook number n of Qn (by table look-up)
* at this stage, n=0,2,3,4 or out=100
*----------------------------------------------------------------*/
*n = Da_nq_fx[*ka];
move16();
/*----------------------------------------------------------------*
* decompose y into :
* (if n<=4:)
* y = c where c is in Q0, Q2, Q3 or Q4
* or
* (if n>4:)
* y = m c + v where c is in Q3 or Q4, v is a Voronoi codevector
* m=2^r (r integer >=2)
*
* in the latter case (if n>4), as a side-product, compute the (Voronoi) index k[] of v
* and replace n by n = n' + 2r where n' = 3 or 4 (c is in Qn') and r is defined above
*----------------------------------------------------------------*/
IF( sub(*n, 4) <= 0 )
{
Copy( y, c, 8 );
}
ELSE
{
/*------------------------------------------------------------*
* initialize r and m=2^r based on || y ||^2/8
*------------------------------------------------------------*/
Ltmp = L_mult(y[0], y[0]);
FOR( i = 1; i < 8; i++ )
{
Ltmp = L_mac( Ltmp, y[i], y[i]);
}
Lsphere = L_shr(Ltmp, 5+1); /* *0.125*0.25 / 2 to remove L_mac effect */
r = 1;
move16();
FOR( ; Lsphere > 11; Lsphere >>= 2 )
{
r = add(r, 1);
}
/*------------------------------------------------------------*
* compute the coordinates of y in the RE8 basis
*------------------------------------------------------------*/
re8_coord_fx( y, k_mod );
/*------------------------------------------------------------*
* compute m and the mask needed for modulo m (for Voronoi coding)
*------------------------------------------------------------*/
mask = sub(shl(1, r), 1); /* 0x0..011...1 */
/*------------------------------------------------------------*
* find the minimal value of r (or equivalently of m) in 2 iterations
*------------------------------------------------------------*/
FOR( iter=0; iter<2; iter++ )
{
/*--------------------------------------------------------*
* compute v such that y is in m RE_8 +v (by Voronoi coding)
*--------------------------------------------------------*/
FOR( i=0; i<8; i++ )
{
k_tmp[i] = s_and( k_mod[i], mask);
move16();
}
re8_k2y_fx( k_tmp, r, v );
/*--------------------------------------------------------*
* compute c = (y-v)/m
* (y is in RE8, c is also in RE8 by definition of v)
*--------------------------------------------------------*/
FOR( i=0; i<8; i++ )
{
c_tmp[i] = shr(sub(y[i], v[i]), r);
move16();
}
/*--------------------------------------------------------*
* verify if c_tmp is in Q2, Q3 or Q4
*--------------------------------------------------------*/
ka_tmp = re8_identify_absolute_leader_fx( c_tmp );
/*--------------------------------------------------------*
* at this stage, n_tmp=2,3,4 or out = 100 -- n=0 is not possible
*--------------------------------------------------------*/
n_tmp = Da_nq_fx[ka_tmp];
move16();
IF( sub(n_tmp, 4) > 0 )
{
/*--------------------------------------------------------*
* if c is not in Q2, Q3, or Q4 (i.e. n_tmp>4), use m = 2^(r+1) instead of 2^r
*--------------------------------------------------------*/
r = add(r, 1);
mask = add(shl(mask, 1), 1); /* mask = m-1 <- this is less complex */
}
ELSE
{
/*--------------------------------------------------------*
* c is in Q2, Q3, or Q4 -> the decomposition of y as y = m c + v is valid
*
* since Q2 is a subset of Q3, indicate n=3 instead of n=2 (this is because
* for n>4, n=n'+2r with n'=3 or 4, so n'=2 is not valid)
*--------------------------------------------------------*/
n_tmp = s_max(n_tmp, 3);
/*--------------------------------------------------------*
* save current values into ka, n, k and c
*--------------------------------------------------------*/
*ka = ka_tmp;
move16();
*n = add(n_tmp, shl(r, 1));
move16();
Copy( k_tmp, k, 8 );
Copy( c_tmp, c, 8 );
/*--------------------------------------------------------*
* try m = 2^(r-1) instead of 2^r to be sure that m is minimal
*--------------------------------------------------------*/
r = sub(r, 1);
mask = shr(mask, 1);
}
}
}
return;
}
/*-------------------------------------------------------------------------
* re8_k2y_fx()
*
* VORONOI INDEXING (INDEX DECODING) k -> y
-------------------------------------------------------------------------*/
void re8_k2y_fx(
const Word16 *k, /* i : Voronoi index k[0..7] */
const Word16 m, /* i : Voronoi modulo (m = 2^r = 1<<r, where r is integer >=2) */
Word16 *y /* o : 8-dimensional point y[0..7] in RE8 */
)
{
Word16 i, v[8], *ptr1, *ptr2, m_tmp, mm;
Word32 ytp[8], z[8], Ltmp, Lsum ;
/*---------------------------------------------------------------*
* compute y = k M and z=(y-a)/m, where
* M = [4 ]
* [2 2 ]
* [| \ ]
* [2 2 ]
* [1 1 _ 1 1]
* a=(2,0,...,0)
*---------------------------------------------------------------*/
m_tmp = sub(15, m);
Lsum = L_deposit_l(k[7]);
ytp[7] = Lsum;
move32();
z[7] = L_shl(Lsum, m_tmp);
move32(); /* (int)(floor(y[7]*QR+0.5))>>m */
FOR( i=6; i>=1; i-- )
{
Ltmp = L_deposit_l( shl(k[i],1) );
Lsum = L_add (Lsum, Ltmp);
ytp[i] = L_add(ytp[7], Ltmp);
move32();
z[i] = L_shl(ytp[i], m_tmp);
move32(); /* (int)(floor(y[7]*QR+0.5))>>m */
}
Lsum = L_add( Lsum, L_deposit_l(shl(k[0],2) ));
ytp[0] = Lsum;
move32();
z[0] = L_shl(L_sub(Lsum, 2), m_tmp);
move32(); /* (int)(floor(y[7]*QR+0.5))>>m */
/*---------------------------------------------------------------*
* find nearest neighbor v of z in infinite RE8
*---------------------------------------------------------------*/
re8_PPV_fx( z, v );
/*---------------------------------------------------------------*
* compute y -= m v
*---------------------------------------------------------------*/
ptr1=y;
ptr2=v;
mm = shr(shl(1, m), 1); /* shr to remove effect of L_mult in L_msu */
FOR( i=0; i<8; i++ )
{
Ltmp = L_msu(ytp[i], *ptr2++, mm);
*ptr1++ = extract_l(Ltmp);
}
return;
}
/*-----------------------------------------------------------------------*
* re8_identify_absolute_leader:
*
* IDENTIFY THE ABSOLUTE LEADER RELATED TO y USING A PRE-DEFINED TABLE WHICH
* SPECIFIES THE CODEBOOKS Q0, Q2, Q3 and Q4
-----------------------------------------------------------------------*/
static Word16 re8_identify_absolute_leader_fx( /* o : integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) */
const Word16 y[] /* i : point in RE8 (8-dimensional integer vector) */
)
{
Word16 i,s,id,nb,pos,ka, tmp16;
Word32 Ltmp, Ls;
Word32 C;
const Word16 *ptr;
/*-----------------------------------------------------------------------*
* compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2)
*-----------------------------------------------------------------------*/
Ls = L_mult(y[0], y[0]);
FOR( i = 1; i < 8; i++ )
{
Ls = L_mac( Ls, y[i], y[i]);
}
s = extract_h(L_shl(Ls, 16-(3+1))); /* s can saturate here */
/*-----------------------------------------------------------------------*
* compute the index 0 <= ka <= NB_LEADER+1 which identifies an absolute leader of Q0, Q2, Q3 or Q4
*
* by default, ka=index of last element of the table (to indicate an outlier)
*-----------------------------------------------------------------------*/
/*-------------------------------------------------------------------*
* if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0
*-------------------------------------------------------------------*/
ka = NB_LEADER;
move16();
IF( s != 0 )
{
ka = NB_LEADER+1;
move16();
/*-------------------------------------------------------------------*
* the maximal value of s for y in Q0, Q2, Q3 or Q4 is NB_SPHERE
* if s> NB_SPHERE, y is an outlier (the value of ka is set correctly)
*-------------------------------------------------------------------*/
IF( sub(s, NB_SPHERE) <= 0 )
{
/*---------------------------------------------------------------*
* compute the unique identifier id of the absolute leader related to y:
* s = (y1^4 + ... + y8^4)/8
*---------------------------------------------------------------*/
C = L_mult(y[0], y[0]);
tmp16 = extract_h(L_shl(C, 16-1));
Ltmp = L_mult(tmp16, tmp16);
FOR( i=1; i<8; i++ )
{
C = L_mult(y[i], y[i]);
tmp16 = extract_h(L_shl(C, 16-1));
Ltmp = L_mac(Ltmp, tmp16, tmp16);
}
id = extract_h(L_shl(Ltmp, 16-(3+1))); /* id can saturate to 8192 */
/*---------------------------------------------------------------*
* search for id in table Da_id
* (containing all possible values of id if y is in Q2, Q3 or Q4)
* this search is focused based on the shell number s so that
* only the id's related to the shell of number s are checked
*---------------------------------------------------------------*/
nb = Da_nb_fx[s - 1]; /* get the number of absolute leaders used on the shell of number s */
pos = Da_pos_fx[s - 1]; /* get the position of the first absolute leader of shell s in Da_id */
move16();
move16();
ptr = &Da_id_fx[pos];
move16();
FOR( i=0; i<nb; i++ )
{
IF( sub(id, *ptr) == 0 )
{
ka = pos;
move16(); /* get ka */
BREAK;
}
ptr++;
pos = add(pos,1);
}
}
}
return( ka );
}
/*-------------------------------------------------------------------------
* Re8_coord:
*
* COMPUTATION OF RE8 COORDINATES
-----------------------------------------------------------------------*/
static void re8_coord_fx(
const Word16 *y, /* i : 8-dimensional point y[0..7] in RE8 */
Word16 *k /* o : coordinates k[0..7] */
)
{
Word16 i, tmp, sum;
/*---------------------------------------------------------------*
* compute k = y M^-1
* M = 1/4 [ 1 ]
* [-1 2 ]
* [ | \ ]
* [-1 2 ]
* [ 5 -2 _ -2 4]
*
*---------------------------------------------------------------*/
k[7] = y[7];
move16();
tmp = y[7];
move16();
sum = add(y[7], shl(y[7], 2));
FOR( i=6; i>=1; i-- )
{
/* apply factor 2/4 from M^-1 */
k[i] = shr(sub(y[i], tmp), 1);
move16();
sum = sub(sum, y[i]);
}
/* apply factor 1/4 from M^-1 */
k[0]= shr(add(y[0], sum), 2);
move16();
return;
}
+62
View File
@@ -0,0 +1,62 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h" /* required for wmc_tool */
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Static table prototypes */
/*--------------------------------------------------------------------------*
* recovernorm_fx()
*
* Recover reordered quantization indices and norms
*--------------------------------------------------------------------------*/
void recovernorm_fx(
Word16 *idxbuf, /* i : reordered quantization indices */
Word16 *ynrm, /* o : recovered quantization indices */
Word16 *normqlg2, /* o : recovered quantized norms */
Word16 nb_sfm /* i : number of SFMs */
)
{
Word16 i,j,k;
const Word16 *order = NULL;
move16();
SWITCH (nb_sfm)
{
case NB_SFM:
order = norm_order_48;
move16();
BREAK;
case SFM_N_SWB:
order = norm_order_32;
move16();
BREAK;
case SFM_N_WB:
order = norm_order_16;
move16();
BREAK;
default:
order = norm_order_48;
move16();
BREAK;
}
FOR (i = 0; i < nb_sfm; i++)
{
j = order[i];
move16();
k = idxbuf[i];
move16();
ynrm[j] = k;
move16();
normqlg2[j] = dicnlg2[k];
move16();
}
return;
}
+58
View File
@@ -0,0 +1,58 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h"
#include "prot_fx.h" /* Function prototypes */
/*--------------------------------------------------------------------------*
* reordvct()
*
* Rearrange a vector in decreasing order
*--------------------------------------------------------------------------*/
void reordvct_fx(
Word16 *y, /* i/o: vector to rearrange */
const Word16 N, /* i : dimensions */
Word16 *idx /* o : reordered vector index */
)
{
Word16 i, j, k, n, im, temp;
n = sub(N, 1);
move16();
FOR (i=0; i<n; i++)
{
im = i;
move16();
k = add(i, 1);
move16();
FOR (j=k; j<N; j++)
{
if ( sub(y[im], y[j]) < 0 )
{
im = j;
move16();
}
}
temp = y[i];
move16();
y[i] = y[im];
move16();
y[im] = temp;
move16();
j = idx[i];
move16();
idx[i] = idx[im];
move16();
idx[im] = j;
move16();
}
return;
}
+228
View File
@@ -0,0 +1,228 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "rom_com_fx.h" /* Function prototypes */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h"
/*--------------------------------------------------------------------*
* Residu3_lc_fx:
*
* Compute the LP residual by filtering the input speech through A(z)
* Output is in Qx
*
* Optimized Version: Use when Past[0..m-1] is 0 & a[0] is 1 (in Q12)
*--------------------------------------------------------------------*/
void Residu3_lc_fx(
const Word16 a[], /* i : prediction coefficients Q12 */
const Word16 m, /* i : order of LP filter Q0 */
const Word16 x[], /* i : input signal (usually speech) Qx */
Word16 y[], /* o : output signal (usually residual) Qx */
const Word16 lg, /* i : vector size Q0 */
const Word16 shift
)
{
Word16 i, j;
Word32 s;
Word16 q;
q = add( norm_s(a[0]), 1 );
if (shift > 0)
q = add(q, shift);
*y++ = shl(x[0], shift);
move16();
FOR (i = 1; i < m; i++)
{
s = L_mult(x[i], a[0]);
/* Stop at i to Avoid Mults with Zeros */
FOR (j = 1; j <= i; j++)
{
s = L_mac(s, x[i-j], a[j]);
}
s = L_shl(s, q);
*y++ = round_fx(s);
}
FOR (; i < lg; i++)
{
s = L_mult(x[i], a[0]);
FOR (j = 1; j <= m; j++)
{
s = L_mac(s, x[i-j], a[j]);
}
s = L_shl(s, q);
*y++ = round_fx(s);
}
}
/*--------------------------------------------------------------------*
* Residu3_10_fx:
*
* Compute the LP residual by filtering the input speech through A(z)
* Output is in Qx
*--------------------------------------------------------------------*/
void Residu3_10_fx(
const Word16 a[], /* i : prediction coefficients Q12 */
const Word16 x[], /* i : input signal (usually speech) Qx */
/* (note that values x[-10..-1] are needed) */
Word16 y[], /* o : output signal (usually residual) Qx */
const Word16 lg, /* i : vector size Q0 */
const Word16 shift
)
{
Word16 i;
Word32 s;
Word16 q;
q = add( norm_s(a[0]), 1 );
if (shift != 0)
q = add(q, shift);
FOR (i = 0; i < lg; i++)
{
s = L_mult(x[i], a[0]);
s = L_mac(s, x[i-1], a[1]);
s = L_mac(s, x[i-2], a[2]);
s = L_mac(s, x[i-3], a[3]);
s = L_mac(s, x[i-4], a[4]);
s = L_mac(s, x[i-5], a[5]);
s = L_mac(s, x[i-6], a[6]);
s = L_mac(s, x[i-7], a[7]);
s = L_mac(s, x[i-8], a[8]);
s = L_mac(s, x[i-9], a[9]);
s = L_mac(s, x[i-10], a[10]);
s = L_shl(s, q);
y[i] = round_fx(s);
}
}
/*--------------------------------------------------------------------*
* Residu3_fx:
*
* Compute the LP residual by filtering the input speech through A(z)
* Output is in Qx
*--------------------------------------------------------------------*/
void Residu3_fx(
const Word16 a[], /* i : prediction coefficients Q12 */
const Word16 x[], /* i : input signal (usually speech) Qx */
/* (note that values x[-M..-1] are needed) */
Word16 y[], /* o : output signal (usually residual) Qx */
const Word16 lg, /* i : vector size Q0 */
const Word16 shift
)
{
Word16 i;
Word32 s;
Word16 q;
q = add( norm_s(a[0]), 1 );
if (shift != 0)
q = add(q, shift);
FOR (i = 0; i < lg; i++)
{
s = L_mult(x[i], a[0]);
s = L_mac(s, x[i-1], a[1]);
s = L_mac(s, x[i-2], a[2]);
s = L_mac(s, x[i-3], a[3]);
s = L_mac(s, x[i-4], a[4]);
s = L_mac(s, x[i-5], a[5]);
s = L_mac(s, x[i-6], a[6]);
s = L_mac(s, x[i-7], a[7]);
s = L_mac(s, x[i-8], a[8]);
s = L_mac(s, x[i-9], a[9]);
s = L_mac(s, x[i-10], a[10]);
s = L_mac(s, x[i-11], a[11]);
s = L_mac(s, x[i-12], a[12]);
s = L_mac(s, x[i-13], a[13]);
s = L_mac(s, x[i-14], a[14]);
s = L_mac(s, x[i-15], a[15]);
s = L_mac(s, x[i-16], a[16]);
s = L_shl(s, q);
y[i] = round_fx(s);
}
}
/*==========================================================================*/
/* FUNCTION : void calc_residu() */
/*--------------------------------------------------------------------------*/
/* PURPOSE : Compute the LP residual by filtering the input through */
/* A(z) in all subframes */
/*--------------------------------------------------------------------------*/
/* INPUT ARGUMENTS : */
/* Word16 *speech i : weighted speech signal Qx */
/* Word16 L_frame i : order of LP filter Q0 */
/* Word16 *p_Aq i : quantized LP filter coefficients Q12 */
/*--------------------------------------------------------------------------*/
/* OUTPUT ARGUMENTS : */
/* Word16 *res o : residual signal Qx+1 */
/*--------------------------------------------------------------------------*/
/* INPUT/OUTPUT ARGUMENTS : */
/*--------------------------------------------------------------------------*/
/* RETURN ARGUMENTS : */
/* _ None */
/*--------------------------------------------------------------------------*/
/* CALLED FROM : */
/*==========================================================================*/
void calc_residu_fx(
Encoder_State_fx *st, /* i/o: state structure */
const Word16 *speech, /* i : weighted speech signal */
Word16 *res, /* o : residual signal */
const Word16 *p_Aq, /* i : quantized LP filter coefficients */
const Word16 vad_hover_flag
)
{
Word16 i_subfr;
Word16 i;
Word16 att;
Word16 offset;
FOR( i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR )
{
/* calculate the residual signal */
Residu3_fx( p_Aq, &speech[i_subfr], &res[i_subfr], L_SUBFR, 1 );
/* next subframe */
p_Aq += (M+1);
}
/* smoothing in case of CNG */
test();
IF( (st->Opt_DTX_ON_fx != 0 ) && (vad_hover_flag != 0) ) /* corresponds to line 504 in FLT acelp_core_enc.c */
{
st->burst_ho_cnt_fx = add(st->burst_ho_cnt_fx,1);
st->burst_ho_cnt_fx = s_min(st->burst_ho_cnt_fx, HO_HIST_SIZE);
IF( sub(st->bwidth_fx, NB) != 0)
{
offset = 5;
test();
if( sub(st->bwidth_fx, WB) == 0 && st->CNG_mode_fx >= 0 )
{
offset = st->CNG_mode_fx;
move16();
}
att = CNG_burst_att_fx[offset][sub(st->burst_ho_cnt_fx,1)]; /*Q15*/
FOR( i = 0; i < st->L_frame_fx; i++ )
{
res[i] = mult_r(res[i], att);
move16();
}
}
}
ELSE
{
st->burst_ho_cnt_fx = 0;
move16();
}
return;
}
+991
View File
@@ -0,0 +1,991 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "rom_basop_util.h"
#include "stl.h"
#include <assert.h>
#include <stdlib.h>
#include "options.h"
/**
* \brief Lookup-Table for binary logarithm
*/
const Word16 ldCoeff[7] =
{
-32768, -16384, -10923, -8192, -6554, -5461, -4681
/* -4096, -3641, -3277 */
};
/**
\brief Lookup-Table for binary power algorithm
This table is used for lookup 2^x with
x in range [0...1.0[ in steps of 1/32
*/
const UWord32 exp2_tab_long[32] =
{
0x40000000,0x4166C34C,0x42D561B4,0x444C0740,
0x45CAE0F2,0x47521CC6,0x48E1E9BA,0x4A7A77D4,
0x4C1BF829,0x4DC69CDD,0x4F7A9930,0x51382182,
0x52FF6B55,0x54D0AD5A,0x56AC1F75,0x5891FAC1,
0x5A82799A,0x5C7DD7A4,0x5E8451D0,0x60962665,
0x62B39509,0x64DCDEC3,0x6712460B,0x69540EC9,
0x6BA27E65,0x6DFDDBCC,0x70666F76,0x72DC8374,
0x75606374,0x77F25CCE,0x7A92BE8B,0x7D41D96E
};
/**
\brief Lookup-Table for binary power algorithm
This table is used for lookup 2^x with
x in range [0...1/32[ in steps of 1/1024
*/
const UWord32 exp2w_tab_long[32] =
{
0x40000000,0x400B1818,0x4016321B,0x40214E0C,
0x402C6BE9,0x40378BB4,0x4042AD6D,0x404DD113,
0x4058F6A8,0x40641E2B,0x406F479E,0x407A7300,
0x4085A051,0x4090CF92,0x409C00C4,0x40A733E6,
0x40B268FA,0x40BD9FFF,0x40C8D8F5,0x40D413DD,
0x40DF50B8,0x40EA8F86,0x40F5D046,0x410112FA,
0x410C57A2,0x41179E3D,0x4122E6CD,0x412E3152,
0x41397DCC,0x4144CC3B,0x41501CA0,0x415B6EFB
};
/**
\brief Lookup-Table for binary power algorithm
This table is used for lookup 2^x with
x in range [0...1/1024[ in steps of 1/32768
*/
const UWord32 exp2x_tab_long[32] =
{
0x40000000,0x400058B9,0x4000B173,0x40010A2D,
0x400162E8,0x4001BBA3,0x4002145F,0x40026D1B,
0x4002C5D8,0x40031E95,0x40037752,0x4003D011,
0x400428CF,0x4004818E,0x4004DA4E,0x4005330E,
0x40058BCE,0x4005E48F,0x40063D51,0x40069613,
0x4006EED5,0x40074798,0x4007A05B,0x4007F91F,
0x400851E4,0x4008AAA8,0x4009036E,0x40095C33,
0x4009B4FA,0x400A0DC0,0x400A6688,0x400ABF4F
};
/* square root tables */
const Word32 SqrtTable[32] = /* Q31 */
{
0x5A82D429, 0x5BEA10FE, 0x5D4BE6E5, 0x5EA89270, 0x60004BE2, 0x615347A1, 0x62A1B68C, 0x63EBC651,
0x6531A1B5, 0x667370D4, 0x67B1595F, 0x68EB7EC8, 0x6A220277, 0x6B5503F0, 0x6C84A0F9, 0x6DB0F5BD,
0x6EDA1CE9, 0x70002FC7, 0x7123465A, 0x72437773, 0x7360D8C5, 0x747B7EFA, 0x75937DC4, 0x76A8E7EB,
0x77BBCF60, 0x78CC4545, 0x79DA5A00, 0x7AE61D3E, 0x7BEF9E07, 0x7CF6EAC2, 0x7DFC113F, 0x7EFF1EC0
};
const Word16 SqrtDiffTable[32] = /* Q21 */
{
0x59CF, 0x5875, 0x572B, 0x55EE, 0x54BF, 0x539C, 0x5284, 0x5177,
0x5074, 0x4F7A, 0x4E89, 0x4DA1, 0x4CC0, 0x4BE7, 0x4B15, 0x4A4A,
0x4985, 0x48C6, 0x480C, 0x4758, 0x46AA, 0x4600, 0x455B, 0x44BA,
0x441D, 0x4385, 0x42F1, 0x4260, 0x41D3, 0x414A, 0x40C3, 0x4040
};
const Word32 ISqrtTable[32] = /* Q31 */
{
0x7FFE7F85, 0x7E0A4E25, 0x7C2C56C7, 0x7A63002C, 0x78ACD922, 0x7708939D, 0x75750088, 0x73F10C2D,
0x727BBB1A, 0x71142774, 0x6FB97EA5, 0x6E6AFF54, 0x6D27F79D, 0x6BEFC388, 0x6AC1CBA4, 0x699D83DA,
0x68826A53, 0x6770068E, 0x6665E882, 0x6563A7DF, 0x6468E364, 0x63754043, 0x62886999, 0x61A20FEE,
0x60C1E8C8, 0x5FE7AE45, 0x5F131EBE, 0x5E43FC76, 0x5D7A0D4F, 0x5CB51A81, 0x5BF4F061, 0x5B395E26
};
const Word16 ISqrtDiffTable[32] = /* Q21 */
{
0x7D0C, 0x777E, 0x7256, 0x6D8A, 0x6911, 0x64E5, 0x60FD, 0x5D54,
0x59E5, 0x56AA, 0x53A0, 0x50C2, 0x4E0D, 0x4B7E, 0x4912, 0x46C6,
0x4499, 0x4288, 0x4090, 0x3EB1, 0x3CE9, 0x3B36, 0x3996, 0x380A,
0x368F, 0x3524, 0x33C9, 0x327C, 0x313D, 0x300B, 0x2EE5, 0x2DCA
};
/* 1/x tables */
const Word32 InvTable[32] = /* Q31 */
{
0x7FFBFE40, 0x7C1B608E, 0x78752176, 0x750440BA, 0x71C44C49, 0x6EB14D0A, 0x6BC7B6B4, 0x69045A19,
0x6664598A, 0x63E51EE2, 0x61845308, 0x5F3FD698, 0x5D15BB8E, 0x5B043FD0, 0x5909C861, 0x5724DD3C,
0x555425B2, 0x53966532, 0x51EA787F, 0x504F5331, 0x4EC3FD84, 0x4D479267, 0x4BD93DBE, 0x4A783ADC,
0x4923D31D, 0x47DB5CAE, 0x469E3974, 0x456BD608, 0x4443A8D9, 0x43253159, 0x420FF746, 0x41038A01
};
/* inverse integer (1/i) */
const Word16 InvIntTable[65] =
{
0x7FFF,
0x7FFF, 0x4000, 0x2AAB, 0x2000, 0x199A, 0x1555, 0x1249, 0x1000,
0x0E39, 0x0CCD, 0x0BA3, 0x0AAB, 0x09D9, 0x0925, 0x0889, 0x0800,
0x0788, 0x071C, 0x06BD, 0x0666, 0x0618, 0x05D1, 0x0591, 0x0555,
0x051F, 0x04EC, 0x04BE, 0x0492, 0x046A, 0x0444, 0x0421, 0x0400,
0x03E1, 0x03C4, 0x03A8, 0x038E, 0x0376, 0x035E, 0x0348, 0x0333,
0x031F, 0x030C, 0x02FA, 0x02E9, 0x02D8, 0x02C8, 0x02B9, 0x02AB,
0x029D, 0x028F, 0x0283, 0x0276, 0x026A, 0x025F, 0x0254, 0x0249,
0x023F, 0x0235, 0x022B, 0x0222, 0x0219, 0x0211, 0x0208, 0x0200
};
const Word16 InvDiffTable[32] = /* Q20 */
{
0x7C14, 0x74C8, 0x6E1C, 0x67FF, 0x6260, 0x5D33, 0x586C, 0x5400,
0x4FE7, 0x4C19, 0x4890, 0x4543, 0x422F, 0x3F4F, 0x3C9D, 0x3A17,
0x37B8, 0x357E, 0x3365, 0x316B, 0x2F8D, 0x2DCB, 0x2C20, 0x2A8D,
0x290F, 0x27A4, 0x264C, 0x2506, 0x23CF, 0x22A7, 0x218E, 0x2081
};
const Word32 BASOP_util_normReciprocal[CHEAP_NORM_SIZE] =
{
0l/*0.0 Q31*/, 2147483647l/*1.0000000000 Q31*/, 1073741824l/*0.5000000000 Q31*/, 715827883l/*0.3333333333 Q31*/, 536870912l/*0.2500000000 Q31*/, 429496730l/*0.2000000000 Q31*/,
357913941l/*0.1666666667 Q31*/, 306783378l/*0.1428571429 Q31*/, 268435456l/*0.1250000000 Q31*/, 238609294l/*0.1111111111 Q31*/, 214748365l/*0.1000000000 Q31*/, 195225786l/*0.0909090909 Q31*/,
178956971l/*0.0833333333 Q31*/, 165191050l/*0.0769230769 Q31*/, 153391689l/*0.0714285714 Q31*/, 143165577l/*0.0666666667 Q31*/, 134217728l/*0.0625000000 Q31*/, 126322568l/*0.0588235294 Q31*/,
119304647l/*0.0555555556 Q31*/, 113025455l/*0.0526315789 Q31*/, 107374182l/*0.0500000000 Q31*/, 102261126l/*0.0476190476 Q31*/, 97612893l/*0.0454545455 Q31*/, 93368854l/*0.0434782609 Q31*/,
89478485l/*0.0416666667 Q31*/, 85899346l/*0.0400000000 Q31*/, 82595525l/*0.0384615385 Q31*/, 79536431l/*0.0370370370 Q31*/, 76695845l/*0.0357142857 Q31*/, 74051160l/*0.0344827586 Q31*/,
71582788l/*0.0333333333 Q31*/, 69273666l/*0.0322580645 Q31*/, 67108864l/*0.0312500000 Q31*/, 65075262l/*0.0303030303 Q31*/, 63161284l/*0.0294117647 Q31*/, 61356676l/*0.0285714286 Q31*/,
59652324l/*0.0277777778 Q31*/, 58040099l/*0.0270270270 Q31*/, 56512728l/*0.0263157895 Q31*/, 55063683l/*0.0256410256 Q31*/, 53687091l/*0.0250000000 Q31*/, 52377650l/*0.0243902439 Q31*/,
51130563l/*0.0238095238 Q31*/, 49941480l/*0.0232558140 Q31*/, 48806446l/*0.0227272727 Q31*/, 47721859l/*0.0222222222 Q31*/, 46684427l/*0.0217391304 Q31*/, 45691141l/*0.0212765957 Q31*/,
44739243l/*0.0208333333 Q31*/, 43826197l/*0.0204081633 Q31*/, 42949673l/*0.0200000000 Q31*/, 42107522l/*0.0196078431 Q31*/, 41297762l/*0.0192307692 Q31*/, 40518559l/*0.0188679245 Q31*/,
39768216l/*0.0185185185 Q31*/, 39045157l/*0.0181818182 Q31*/, 38347922l/*0.0178571429 Q31*/, 37675152l/*0.0175438596 Q31*/, 37025580l/*0.0172413793 Q31*/, 36398028l/*0.0169491525 Q31*/,
35791394l/*0.0166666667 Q31*/, 35204650l/*0.0163934426 Q31*/, 34636833l/*0.0161290323 Q31*/, 34087042l/*0.0158730159 Q31*/, 33554432l/*0.0156250000 Q31*/, 33038210l/*0.0153846154 Q31*/,
32537631l/*0.0151515152 Q31*/, 32051995l/*0.0149253731 Q31*/, 31580642l/*0.0147058824 Q31*/, 31122951l/*0.0144927536 Q31*/, 30678338l/*0.0142857143 Q31*/, 30246248l/*0.0140845070 Q31*/,
29826162l/*0.0138888889 Q31*/, 29417584l/*0.0136986301 Q31*/, 29020049l/*0.0135135135 Q31*/, 28633115l/*0.0133333333 Q31*/, 28256364l/*0.0131578947 Q31*/, 27889398l/*0.0129870130 Q31*/,
27531842l/*0.0128205128 Q31*/, 27183337l/*0.0126582278 Q31*/, 26843546l/*0.0125000000 Q31*/, 26512144l/*0.0123456790 Q31*/, 26188825l/*0.0121951220 Q31*/, 25873297l/*0.0120481928 Q31*/,
25565282l/*0.0119047619 Q31*/, 25264514l/*0.0117647059 Q31*/, 24970740l/*0.0116279070 Q31*/, 24683720l/*0.0114942529 Q31*/, 24403223l/*0.0113636364 Q31*/, 24129030l/*0.0112359551 Q31*/,
23860929l/*0.0111111111 Q31*/, 23598721l/*0.0109890110 Q31*/, 23342214l/*0.0108695652 Q31*/, 23091222l/*0.0107526882 Q31*/, 22845571l/*0.0106382979 Q31*/, 22605091l/*0.0105263158 Q31*/,
22369621l/*0.0104166667 Q31*/, 22139007l/*0.0103092784 Q31*/, 21913098l/*0.0102040816 Q31*/, 21691754l/*0.0101010101 Q31*/, 21474836l/*0.0100000000 Q31*/, 21262214l/*0.0099009901 Q31*/,
21053761l/*0.0098039216 Q31*/, 20849356l/*0.0097087379 Q31*/, 20648881l/*0.0096153846 Q31*/, 20452225l/*0.0095238095 Q31*/, 20259280l/*0.0094339623 Q31*/, 20069941l/*0.0093457944 Q31*/,
19884108l/*0.0092592593 Q31*/, 19701685l/*0.0091743119 Q31*/, 19522579l/*0.0090909091 Q31*/, 19346700l/*0.0090090090 Q31*/, 19173961l/*0.0089285714 Q31*/, 19004280l/*0.0088495575 Q31*/,
18837576l/*0.0087719298 Q31*/, 18673771l/*0.0086956522 Q31*/, 18512790l/*0.0086206897 Q31*/, 18354561l/*0.0085470085 Q31*/, 18199014l/*0.0084745763 Q31*/, 18046081l/*0.0084033613 Q31*/,
17895697l/*0.0083333333 Q31*/, 17747799l/*0.0082644628 Q31*/, 17602325l/*0.0081967213 Q31*/, 17459217l/*0.0081300813 Q31*/, 17318416l/*0.0080645161 Q31*/, 17179869l/*0.0080000000 Q31*/,
17043521l/*0.0079365079 Q31*/, 16909320l/*0.0078740157 Q31*/, 16777216l/*0.0078125000 Q31*/, 16647160l/*0.0077519380 Q31*/, 16519105l/*0.0076923077 Q31*/, 16393005l/*0.0076335878 Q31*/,
16268816l/*0.0075757576 Q31*/, 16146494l/*0.0075187970 Q31*/, 16025997l/*0.0074626866 Q31*/, 15907286l/*0.0074074074 Q31*/, 15790321l/*0.0073529412 Q31*/, 15675063l/*0.0072992701 Q31*/,
15561476l/*0.0072463768 Q31*/, 15449523l/*0.0071942446 Q31*/, 15339169l/*0.0071428571 Q31*/, 15230381l/*0.0070921986 Q31*/, 15123124l/*0.0070422535 Q31*/, 15017368l/*0.0069930070 Q31*/,
14913081l/*0.0069444444 Q31*/, 14810232l/*0.0068965517 Q31*/, 14708792l/*0.0068493151 Q31*/, 14608732l/*0.0068027211 Q31*/, 14510025l/*0.0067567568 Q31*/, 14412642l/*0.0067114094 Q31*/,
14316558l/*0.0066666667 Q31*/, 14221746l/*0.0066225166 Q31*/, 14128182l/*0.0065789474 Q31*/, 14035841l/*0.0065359477 Q31*/, 13944699l/*0.0064935065 Q31*/, 13854733l/*0.0064516129 Q31*/,
13765921l/*0.0064102564 Q31*/, 13678240l/*0.0063694268 Q31*/, 13591669l/*0.0063291139 Q31*/, 13506187l/*0.0062893082 Q31*/, 13421773l/*0.0062500000 Q31*/
};
const Word16 f_atan_expand_range[MAXSFTAB-(MINSFTAB-1)] =
{
/*****************************************************************************
*
* Table holds fixp_atan() output values which are outside of input range
* of fixp_atan() to improve SNR of fixp_atan2().
*
* This Table might also be used in fixp_atan() [todo] so there a wider input
* range can be covered, too.
*
* Matlab (generate table):
* for scl = 7:25 % MINSFTAB .. MAXSFTAB
* at=atan(0.5 *(2^scl)); % 0.5 because get in 'middle' area of current scale level 'scl'
* at/2 % div at by ATO_SCALE
* end
*
* Table divided by 2=ATO_SCALE <-- SF=ATO_SF
*****************************************************************************/
25480/*7.775862990872099e-001 Q15*/, 25608/*7.814919928673978e-001 Q15*/, 25672/*7.834450483314648e-001 Q15*/,
25704/*7.844216021392089e-001 Q15*/, 25720/*7.849098823026687e-001 Q15*/, 25728/*7.851540227918509e-001 Q15*/,
25732/*7.852760930873737e-001 Q15*/, 25734/*7.853371282415015e-001 Q15*/, 25735/*7.853676458193612e-001 Q15*/,
25735/*7.853829046083906e-001 Q15*/, 25736/*7.853905340029177e-001 Q15*/, 25736/*7.853943487001828e-001 Q15*/,
25736/*7.853962560488155e-001 Q15*/, 25736/*7.853972097231319e-001 Q15*/, 25736/*7.853976865602901e-001 Q15*/,
25736/*7.853979249788692e-001 Q15*/, 25736/*7.853980441881587e-001 Q15*/, 25736/*7.853981037928035e-001 Q15*/,
25736/*7.853981335951259e-001 Q15*/
/* pi/4 = 0.785398163397448 = pi/2/ATO_SCALE */
};
/*
Sine tables
*/
#define STC(x) WORD322WORD16(x)
/* #define STCP(a,b) (((Word32)STC(b)<<16) | STC(a)) */
#define STCP(a,b) { { STC(a), STC(b) } }
const PWord16 SineTable512[] =
{
STCP(0x7fffffff, 0x00000000), STCP(0x7fffd886, 0x006487e3), STCP(0x7fff6216, 0x00c90f88), STCP(0x7ffe9cb2, 0x012d96b1),
STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffc250f, 0x01f6a297), STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff871a2, 0x02bfa9a4),
STCP(0x7ff62182, 0x03242abf), STCP(0x7ff38274, 0x0388a9ea), STCP(0x7ff09478, 0x03ed26e6), STCP(0x7fed5791, 0x0451a177),
STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe5f108, 0x051a8e5c), STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdd4eec, 0x05e36ea9),
STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd37153, 0x06ac406f), STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fc85854, 0x077501be),
STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbc040a, 0x083db0a7), STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fae7495, 0x09064b3a),
STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9faa15, 0x09cecf89), STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f8fa4b0, 0x0a973ba5),
STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f7e648c, 0x0b5f8d9f), STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f6be9d4, 0x0c27c389),
STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5834b7, 0x0cefdb76), STCP(0x7f4de451, 0x0d53db92), STCP(0x7f434563, 0x0db7d376),
STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f2d1c0e, 0x0e7fa99e), STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f15b8ee, 0x0f475bff),
STCP(0x7f0991c4, 0x0fab272b), STCP(0x7efd1c3c, 0x100ee8ad), STCP(0x7ef05860, 0x1072a048), STCP(0x7ee34636, 0x10d64dbd),
STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ec8371a, 0x119d8941), STCP(0x7eba3a39, 0x120116d5), STCP(0x7eabef2c, 0x1264994e),
STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8e6eb2, 0x132b7bf9), STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e6fb5f4, 0x13f22f58),
STCP(0x7e5fe493, 0x145576b1), STCP(0x7e4fc53e, 0x14b8b17f), STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e2e9cdf, 0x157f0086),
STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e0c3d29, 0x16451a83), STCP(0x7dfa98a8, 0x16a81305), STCP(0x7de8a670, 0x170afd8d),
STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dc3d90d, 0x17d0a7bc), STCP(0x7db0fdf8, 0x183366e9), STCP(0x7d9dd55a, 0x18961728),
STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d769bb5, 0x195b49ea), STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d4e2c7f, 0x1a203e1b),
STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d24881b, 0x1ae4f1d6), STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7cf9aef0, 0x1ba96335),
STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7ccda169, 0x1c6d9053), STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7ca05ff1, 0x1d31774d),
STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c71eaf9, 0x1df5163f), STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4242f2, 0x1eb86b46),
STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c116853, 0x1f7b7481), STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bdf5b94, 0x203e300d),
STCP(0x7bc5e290, 0x209f701c), STCP(0x7bac1d31, 0x21009c0c), STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b77ada8, 0x21c2b69c),
STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b420d7a, 0x22847de0), STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b0b3d2c, 0x2345eff8),
STCP(0x7aef6323, 0x23a6887f), STCP(0x7ad33d45, 0x24070b08), STCP(0x7ab6cba4, 0x24677758), STCP(0x7a9a0e50, 0x24c7cd33),
STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5fb0d8, 0x2588349d), STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a24256f, 0x26483f6c),
STCP(0x7a05eead, 0x26a82186), STCP(0x79e76ca7, 0x2707ebc7), STCP(0x79c89f6e, 0x27679df4), STCP(0x79a98715, 0x27c737d3),
STCP(0x798a23b1, 0x2826b928), STCP(0x796a7554, 0x288621b9), STCP(0x794a7c12, 0x28e5714b), STCP(0x792a37fe, 0x2944a7a2),
STCP(0x7909a92d, 0x29a3c485), STCP(0x78e8cfb2, 0x2a02c7b8), STCP(0x78c7aba2, 0x2a61b101), STCP(0x78a63d11, 0x2ac08026),
STCP(0x78848414, 0x2b1f34eb), STCP(0x786280bf, 0x2b7dcf17), STCP(0x78403329, 0x2bdc4e6f), STCP(0x781d9b65, 0x2c3ab2b9),
STCP(0x77fab989, 0x2c98fbba), STCP(0x77d78daa, 0x2cf72939), STCP(0x77b417df, 0x2d553afc), STCP(0x7790583e, 0x2db330c7),
STCP(0x776c4edb, 0x2e110a62), STCP(0x7747fbce, 0x2e6ec792), STCP(0x77235f2d, 0x2ecc681e), STCP(0x76fe790e, 0x2f29ebcc),
STCP(0x76d94989, 0x2f875262), STCP(0x76b3d0b4, 0x2fe49ba7), STCP(0x768e0ea6, 0x3041c761), STCP(0x76680376, 0x309ed556),
STCP(0x7641af3d, 0x30fbc54d), STCP(0x761b1211, 0x3158970e), STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75ccfd42, 0x3211df04),
STCP(0x75a585cf, 0x326e54c7), STCP(0x757dc5ca, 0x32caab6f), STCP(0x7555bd4c, 0x3326e2c3), STCP(0x752d6c6c, 0x3382fa88),
STCP(0x7504d345, 0x33def287), STCP(0x74dbf1ef, 0x343aca87), STCP(0x74b2c884, 0x34968250), STCP(0x7489571c, 0x34f219a8),
STCP(0x745f9dd1, 0x354d9057), STCP(0x74359cbd, 0x35a8e625), STCP(0x740b53fb, 0x36041ad9), STCP(0x73e0c3a3, 0x365f2e3b),
STCP(0x73b5ebd1, 0x36ba2014), STCP(0x738acc9e, 0x3714f02a), STCP(0x735f6626, 0x376f9e46), STCP(0x7333b883, 0x37ca2a30),
STCP(0x7307c3d0, 0x382493b0), STCP(0x72db8828, 0x387eda8e), STCP(0x72af05a7, 0x38d8fe93), STCP(0x72823c67, 0x3932ff87),
STCP(0x72552c85, 0x398cdd32), STCP(0x7227d61c, 0x39e6975e), STCP(0x71fa3949, 0x3a402dd2), STCP(0x71cc5626, 0x3a99a057),
STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x716fbd68, 0x3b4c18ba), STCP(0x71410805, 0x3ba51e29), STCP(0x71120cc5, 0x3bfdfecd),
STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b34525, 0x3caf50da), STCP(0x708378ff, 0x3d07c1d6), STCP(0x70536771, 0x3d600d2c),
STCP(0x7023109a, 0x3db832a6), STCP(0x6ff27497, 0x3e10320d), STCP(0x6fc19385, 0x3e680b2c), STCP(0x6f906d84, 0x3ebfbdcd),
STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f2d532c, 0x3f6eaeb8), STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ec92683, 0x401d0321),
STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e63e87f, 0x40cab958), STCP(0x6e30e34a, 0x4121589b), STCP(0x6dfd9a1c, 0x4177cfb1),
STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d963c54, 0x42244481), STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d2dd027, 0x42d0161e),
STCP(0x6cf934fc, 0x4325c135), STCP(0x6cc45698, 0x437b42e1), STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c59d0a9, 0x4425c923),
STCP(0x6c242960, 0x447acd50), STCP(0x6bee3f62, 0x44cfa740), STCP(0x6bb812d1, 0x452456bd), STCP(0x6b81a3cd, 0x4578db93),
STCP(0x6b4af279, 0x45cd358f), STCP(0x6b13fef5, 0x4621647d), STCP(0x6adcc964, 0x46756828), STCP(0x6aa551e9, 0x46c9405c),
STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a359db9, 0x47706d93), STCP(0x69fd614a, 0x47c3c22f), STCP(0x69c4e37a, 0x4816ea86),
STCP(0x698c246c, 0x4869e665), STCP(0x69532442, 0x48bcb599), STCP(0x6919e320, 0x490f57ee), STCP(0x68e06129, 0x4961cd33),
STCP(0x68a69e81, 0x49b41533), STCP(0x686c9b4b, 0x4a062fbd), STCP(0x683257ab, 0x4a581c9e), STCP(0x67f7d3c5, 0x4aa9dba2),
STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x67820bb7, 0x4b4ccf4d), STCP(0x6746c7d8, 0x4b9e0390), STCP(0x670b4444, 0x4bef092d),
STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66937e91, 0x4c9087b1), STCP(0x66573cbb, 0x4ce10034), STCP(0x661abbc5, 0x4d31494b),
STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65a0fd0b, 0x4dd14c6e), STCP(0x6563bf92, 0x4e210617), STCP(0x6526438f, 0x4e708f8f),
STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64aa907f, 0x4f0f1126), STCP(0x646c59bf, 0x4f5e08e3), STCP(0x642de50d, 0x4faccfab),
STCP(0x63ef3290, 0x4ffb654d), STCP(0x63b0426d, 0x5049c999), STCP(0x637114cc, 0x5097fc5e), STCP(0x6331a9d4, 0x50e5fd6d),
STCP(0x62f201ac, 0x5133cc94), STCP(0x62b21c7b, 0x518169a5), STCP(0x6271fa69, 0x51ced46e), STCP(0x62319b9d, 0x521c0cc2),
STCP(0x61f1003f, 0x5269126e), STCP(0x61b02876, 0x52b5e546), STCP(0x616f146c, 0x53028518), STCP(0x612dc447, 0x534ef1b5),
STCP(0x60ec3830, 0x539b2af0), STCP(0x60aa7050, 0x53e73097), STCP(0x60686ccf, 0x5433027d), STCP(0x60262dd6, 0x547ea073),
STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fa0fe1f, 0x55153fd4), STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f1ae274, 0x55ab0d46),
STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e93dc1f, 0x56400758), STCP(0x5e50015d, 0x568a34a9), STCP(0x5e0bec6e, 0x56d42c99),
STCP(0x5dc79d7c, 0x571deefa), STCP(0x5d8314b1, 0x57677b9d), STCP(0x5d3e5237, 0x57b0d256), STCP(0x5cf95638, 0x57f9f2f8),
STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c6eb258, 0x588b9140), STCP(0x5c290acc, 0x58d40e8c), STCP(0x5be32a67, 0x591c550e),
STCP(0x5b9d1154, 0x59646498), STCP(0x5b56bfbd, 0x59ac3cfd), STCP(0x5b1035cf, 0x59f3de12), STCP(0x5ac973b5, 0x5a3b47ab),
STCP(0x5a82799a, 0x5a82799a),
};
const PWord16 SineTable320[] =
{
STCP(0x7fffffff, 0x00000000), STCP(0x7fff9aef, 0x00a0d951),
STCP(0x7ffe6bbf, 0x0141b1a5), STCP(0x7ffc726f, 0x01e287fc),
STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff62182, 0x03242abf),
STCP(0x7ff1c9ef, 0x03c4f52f), STCP(0x7feca851, 0x0465b9aa),
STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fe00716, 0x05a72ccf),
STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd03e23, 0x06e87c3f),
STCP(0x7fc72ae2, 0x07891418), STCP(0x7fbd4dda, 0x0829a00c),
STCP(0x7fb2a71b, 0x08ca1f1b), STCP(0x7fa736b4, 0x096a9049),
STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f8df93c, 0x0aab450d),
STCP(0x7f802c52, 0x0b4b86a8), STCP(0x7f719611, 0x0bebb66c),
STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f520de6, 0x0d2bdc80),
STCP(0x7f411c2f, 0x0dcbd0d5), STCP(0x7f2f6183, 0x0e6baf61),
STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f0991c4, 0x0fab272b),
STCP(0x7ef57cea, 0x104abe71), STCP(0x7ee09f95, 0x10ea3bfd),
STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7eb48bfb, 0x1228e5f8),
STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e85580c, 0x13671d3d),
STCP(0x7e6c9251, 0x14060b68), STCP(0x7e5304f2, 0x14a4d9f4),
STCP(0x7e38b017, 0x154387e6), STCP(0x7e1d93ea, 0x15e21445),
STCP(0x7e01b096, 0x16807e15), STCP(0x7de50646, 0x171ec45c),
STCP(0x7dc79529, 0x17bce621), STCP(0x7da95d6c, 0x185ae269),
STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d6a9ad5, 0x199666a0),
STCP(0x7d4a105d, 0x1a33ec9c), STCP(0x7d28c00c, 0x1ad14938),
STCP(0x7d06aa16, 0x1b6e7b7a), STCP(0x7ce3ceb2, 0x1c0b826a),
STCP(0x7cc02e15, 0x1ca85d12), STCP(0x7c9bc87a, 0x1d450a78),
STCP(0x7c769e18, 0x1de189a6), STCP(0x7c50af2b, 0x1e7dd9a4),
STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c02849f, 0x1fb5e836),
STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bb14ac5, 0x20ed2e7b),
STCP(0x7b8788ba, 0x2188841a), STCP(0x7b5d039e, 0x2223a4c5),
STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7b05b13d, 0x2359436c),
STCP(0x7ad8e482, 0x23f3bf7e), STCP(0x7aab55ca, 0x248e02cb),
STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a4df380, 0x25c1db44),
STCP(0x7a1e2082, 0x265b6e8a), STCP(0x79ed8cad, 0x26f4c53e),
STCP(0x79bc384d, 0x278dde6e), STCP(0x798a23b1, 0x2826b928),
STCP(0x79574f28, 0x28bf547b), STCP(0x7923bb01, 0x2957af74),
STCP(0x78ef678f, 0x29efc925), STCP(0x78ba5524, 0x2a87a09d),
STCP(0x78848414, 0x2b1f34eb), STCP(0x784df4b3, 0x2bb68522),
STCP(0x7816a759, 0x2c4d9050), STCP(0x77de9c5b, 0x2ce45589),
STCP(0x77a5d413, 0x2d7ad3de), STCP(0x776c4edb, 0x2e110a62),
STCP(0x77320d0d, 0x2ea6f827), STCP(0x76f70f05, 0x2f3c9c40),
STCP(0x76bb5521, 0x2fd1f5c1), STCP(0x767edfbe, 0x306703bf),
STCP(0x7641af3d, 0x30fbc54d), STCP(0x7603c3fd, 0x31903982),
STCP(0x75c51e61, 0x32245f72), STCP(0x7585becb, 0x32b83634),
STCP(0x7545a5a0, 0x334bbcde), STCP(0x7504d345, 0x33def287),
STCP(0x74c34820, 0x3471d647), STCP(0x74810499, 0x35046736),
STCP(0x743e0918, 0x3596a46c), STCP(0x73fa5607, 0x36288d03),
STCP(0x73b5ebd1, 0x36ba2014), STCP(0x7370cae2, 0x374b5cb9),
STCP(0x732af3a7, 0x37dc420c), STCP(0x72e4668f, 0x386ccf2a),
STCP(0x729d2409, 0x38fd032d), STCP(0x72552c85, 0x398cdd32),
STCP(0x720c8075, 0x3a1c5c57), STCP(0x71c3204c, 0x3aab7fb7),
STCP(0x71790c7e, 0x3b3a4672), STCP(0x712e457f, 0x3bc8afa5),
STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70969fca, 0x3ce465f3),
STCP(0x7049c203, 0x3d71b14d), STCP(0x6ffc32eb, 0x3dfe9ba1),
STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6f5f02b2, 0x3f1749b8),
STCP(0x6f0f6289, 0x3fa30bc1), STCP(0x6ebf12ff, 0x402e694c),
STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e1c67c4, 0x4143f379),
STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d770506, 0x4257e166),
STCP(0x6d23501b, 0x42e13ba4), STCP(0x6cceeed8, 0x436a2c45),
STCP(0x6c79e1c2, 0x43f2b271), STCP(0x6c242960, 0x447acd50),
STCP(0x6bcdc639, 0x45027c0c), STCP(0x6b76b8d6, 0x4589bdcf),
STCP(0x6b1f01c0, 0x461091c2), STCP(0x6ac6a180, 0x4696f710),
STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a13e7b8, 0x47a27271),
STCP(0x69b98f48, 0x482786dc), STCP(0x695e8fe5, 0x48ac2957),
STCP(0x6902ea1d, 0x4930590f), STCP(0x68a69e81, 0x49b41533),
STCP(0x6849ada3, 0x4a375cf5), STCP(0x67ec1817, 0x4aba2f84),
STCP(0x678dde6e, 0x4b3c8c12), STCP(0x672f013f, 0x4bbe71d1),
STCP(0x66cf8120, 0x4c3fdff4), STCP(0x666f5ea6, 0x4cc0d5ae),
STCP(0x660e9a6a, 0x4d415234), STCP(0x65ad3505, 0x4dc154bb),
STCP(0x654b2f10, 0x4e40dc79), STCP(0x64e88926, 0x4ebfe8a5),
STCP(0x648543e4, 0x4f3e7875), STCP(0x64215fe5, 0x4fbc8b22),
STCP(0x63bcddc7, 0x503a1fe5), STCP(0x6357be2a, 0x50b735f8),
STCP(0x62f201ac, 0x5133cc94), STCP(0x628ba8ef, 0x51afe2f6),
STCP(0x6224b495, 0x522b7859), STCP(0x61bd253f, 0x52a68bfb),
STCP(0x6154fb91, 0x53211d18), STCP(0x60ec3830, 0x539b2af0),
STCP(0x6082dbc1, 0x5414b4c1), STCP(0x6018e6eb, 0x548db9cb),
STCP(0x5fae5a55, 0x55063951), STCP(0x5f4336a7, 0x557e3292),
STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e6b2ca8, 0x566c8f55),
STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5d90ce45, 0x5758ca31),
STCP(0x5d22c11c, 0x57ce1917), STCP(0x5cb420e0, 0x5842dd54),
STCP(0x5c44ee40, 0x58b71632), STCP(0x5bd529eb, 0x592ac2f7),
STCP(0x5b64d492, 0x599de2ee), STCP(0x5af3eee6, 0x5a107561),
STCP(0x5a82799a, 0x5a82799a)
};
/*
Sine windows
*/
#define WTC(x) WORD322WORD16(x)
#define WTCP(a,b) { { WTC(a), WTC(b) } }
const PWord16 SineWindow10[5] =
{
WTCP(0x7f9afcb9, 0x0a0af299), WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x6d23501b, 0x42e13ba4),
WTCP(0x6154fb91, 0x53211d18),
};
const PWord16 SineWindow16[8] =
{
WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x78848414, 0x2b1f34eb),
WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x5ed77c8a, 0x55f5a4d2),
};
const PWord16 SineWindow20[10] =
{
WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7b31bbb2, 0x22be8f87),
WTCP(0x7816a759, 0x2c4d9050), WTCP(0x743e0918, 0x3596a46c), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6a6d98a4, 0x471cece7),
WTCP(0x648543e4, 0x4f3e7875), WTCP(0x5dfe47ad, 0x56e2f15d),
};
const PWord16 SineWindow30[15] =
{
WTCP(0x7ff4c56f, 0x0359c428), WTCP(0x7f9afcb9, 0x0a0af299), WTCP(0x7ee7aa4c, 0x10b5150f), WTCP(0x7ddb4bfc, 0x17537e63),
WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7aba9ae6, 0x245a9d65), WTCP(0x78a879f4, 0x2aba2ee4), WTCP(0x7641af3d, 0x30fbc54d),
WTCP(0x7387ea23, 0x371afcd5), WTCP(0x707d1443, 0x3d1389cb), WTCP(0x6d23501b, 0x42e13ba4), WTCP(0x697cf78a, 0x487fffe4),
WTCP(0x658c9a2d, 0x4debe4fe), WTCP(0x6154fb91, 0x53211d18), WTCP(0x5cd91140, 0x581c00b3),
};
const PWord16 SineWindow32[16] =
{
WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7e1d93ea, 0x15e21445),
WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x798a23b1, 0x2826b928), WTCP(0x776c4edb, 0x2e110a62),
WTCP(0x7504d345, 0x33def287), WTCP(0x72552c85, 0x398cdd32), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6c242960, 0x447acd50),
WTCP(0x68a69e81, 0x49b41533), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x5cb420e0, 0x5842dd54)
};
const PWord16 SineWindow40[20] =
{
WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7ecaf9e5, 0x11899ed3),
WTCP(0x7e01b096, 0x16807e15), WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7a7d055b, 0x25280c5e),
WTCP(0x78ef678f, 0x29efc925), WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x732af3a7, 0x37dc420c),
WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6902ea1d, 0x4930590f),
WTCP(0x660e9a6a, 0x4d415234), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x5fae5a55, 0x55063951), WTCP(0x5c44ee40, 0x58b71632),
};
const PWord16 SineWindow48[24] =
{
WTCP(0x7ffb9d15, 0x02182427), WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f294bfd, 0x0ea0f48c),
WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7deeaa7a, 0x16ea0646), WTCP(0x7d1d7958, 0x1b05b40f), WTCP(0x7c29fbee, 0x1f19f97b),
WTCP(0x7b1474fd, 0x2325b847), WTCP(0x79dd3098, 0x2727d486), WTCP(0x78848414, 0x2b1f34eb), WTCP(0x770acdec, 0x2f0ac320),
WTCP(0x757075ac, 0x32e96c09), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x6fe2313c, 0x3e2d7eb1),
WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6b93d02e, 0x455cb40c), WTCP(0x694015c3, 0x48d84609), WTCP(0x66cf8120, 0x4c3fdff4),
WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x619a7dce, 0x52cf758f), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5bfa7b82, 0x590443a7)
};
const PWord16 SineWindow60[60] =
{
WTCP(0x7ffd3154, 0x01aceb7c), WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7f76892f, 0x0bb65336),
WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e26b371, 0x15ad3e9a), WTCP(0x7d8a5f40, 0x18f8b83c),
WTCP(0x7cd80464, 0x1c3fd045), WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7a3e17f2, 0x25f51307),
WTCP(0x793501a9, 0x2924edac), WTCP(0x7816a759, 0x2c4d9050), WTCP(0x76e33b3f, 0x2f6e6d16), WTCP(0x759af34c, 0x3286f779),
WTCP(0x743e0918, 0x3596a46c), WTCP(0x72ccb9db, 0x389cea72), WTCP(0x71474660, 0x3b9941b1), WTCP(0x6fadf2fc, 0x3e8b240e),
WTCP(0x6e010780, 0x41720d46), WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x6887b5e2, 0x49dfe4c2),
WTCP(0x668f7c25, 0x4c95e688), WTCP(0x648543e4, 0x4f3e7875), WTCP(0x626968be, 0x51d92321), WTCP(0x603c496c, 0x54657194),
WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5bafc837, 0x595132a2),
};
const PWord16 SineWindow64[32] =
{
WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7f872bf3, 0x0afb6805),
WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7dd6668f, 0x176dd9de),
WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7aef6323, 0x23a6887f),
WTCP(0x7a05eead, 0x26a82186), WTCP(0x7909a92d, 0x29a3c485), WTCP(0x77fab989, 0x2c98fbba), WTCP(0x76d94989, 0x2f875262),
WTCP(0x75a585cf, 0x326e54c7), WTCP(0x745f9dd1, 0x354d9057), WTCP(0x7307c3d0, 0x382493b0), WTCP(0x719e2cd2, 0x3af2eeb7),
WTCP(0x7023109a, 0x3db832a6), WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6b4af279, 0x45cd358f),
WTCP(0x698c246c, 0x4869e665), WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x63ef3290, 0x4ffb654d),
WTCP(0x61f1003f, 0x5269126e), WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5b9d1154, 0x59646498),
};
const PWord16 SineWindow80[40] =
{
WTCP(0x7ffe6bbf, 0x0141b1a5), WTCP(0x7ff1c9ef, 0x03c4f52f), WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7fb2a71b, 0x08ca1f1b),
WTCP(0x7f802c52, 0x0b4b86a8), WTCP(0x7f411c2f, 0x0dcbd0d5), WTCP(0x7ef57cea, 0x104abe71), WTCP(0x7e9d55fc, 0x12c8106f),
WTCP(0x7e38b017, 0x154387e6), WTCP(0x7dc79529, 0x17bce621), WTCP(0x7d4a105d, 0x1a33ec9c), WTCP(0x7cc02e15, 0x1ca85d12),
WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7b8788ba, 0x2188841a), WTCP(0x7ad8e482, 0x23f3bf7e), WTCP(0x7a1e2082, 0x265b6e8a),
WTCP(0x79574f28, 0x28bf547b), WTCP(0x78848414, 0x2b1f34eb), WTCP(0x77a5d413, 0x2d7ad3de), WTCP(0x76bb5521, 0x2fd1f5c1),
WTCP(0x75c51e61, 0x32245f72), WTCP(0x74c34820, 0x3471d647), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x729d2409, 0x38fd032d),
WTCP(0x71790c7e, 0x3b3a4672), WTCP(0x7049c203, 0x3d71b14d), WTCP(0x6f0f6289, 0x3fa30bc1), WTCP(0x6dca0d14, 0x41ce1e65),
WTCP(0x6c79e1c2, 0x43f2b271), WTCP(0x6b1f01c0, 0x461091c2), WTCP(0x69b98f48, 0x482786dc), WTCP(0x6849ada3, 0x4a375cf5),
WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x654b2f10, 0x4e40dc79), WTCP(0x63bcddc7, 0x503a1fe5), WTCP(0x6224b495, 0x522b7859),
WTCP(0x6082dbc1, 0x5414b4c1), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5d22c11c, 0x57ce1917), WTCP(0x5b64d492, 0x599de2ee),
};
const PWord16 SineWindow70[35] =
{
WTCP(0x7ffdeffe, 0x016fa5fd), WTCP(0x7fed7058, 0x044ec292), WTCP(0x7fcc732b, 0x072d5101), WTCP(0x7f9afcb9, 0x0a0af299),
WTCP(0x7f591361, 0x0ce748ca), WTCP(0x7f06bfa3, 0x0fc1f52d), WTCP(0x7ea40c1b, 0x129a9991), WTCP(0x7e310583, 0x1570d80b),
WTCP(0x7dadbaaf, 0x184452fd), WTCP(0x7d1a3c8a, 0x1b14ad24), WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7bc2f470, 0x20aa8c19),
WTCP(0x7aff56bc, 0x236f5896), WTCP(0x7a2bde32, 0x262f93be), WTCP(0x7948a614, 0x28eae2cb), WTCP(0x7855cbae, 0x2ba0eb97),
WTCP(0x77536e4c, 0x2e5154ac), WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x7520b1ca, 0x339fe582), WTCP(0x73f09b33, 0x363d5e23),
WTCP(0x72b192ac, 0x38d3d8e3), WTCP(0x7163c154, 0x3b63005e), WTCP(0x70075233, 0x3dea8020), WTCP(0x6e9c7233, 0x406a04b2),
WTCP(0x6d23501b, 0x42e13ba4), WTCP(0x6b9c1c87, 0x454fd398), WTCP(0x6a0709e6, 0x47b57c4e), WTCP(0x68644c6e, 0x4a11e6aa),
WTCP(0x66b41a1a, 0x4c64c4c4), WTCP(0x64f6aa9f, 0x4eadc9ee), WTCP(0x632c3769, 0x50ecaabd), WTCP(0x6154fb91, 0x53211d18),
WTCP(0x5f7133d4, 0x554ad83c), WTCP(0x5d811e90, 0x576994c8), WTCP(0x5b84fbb6, 0x597d0cc7)
};
const PWord16 SineWindow96[48] =
{
WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fca47b9, 0x07538d6b),
WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f7b65ef, 0x0b80edf1), WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f0991c4, 0x0fab272b),
WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7e74ea6a, 0x13d114d0), WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7dbd98a4, 0x17f193c5),
WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7be7c847, 0x201dc0ef),
WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7ac9ca7a, 0x2427319d), WTCP(0x7a2e26f2, 0x26284422), WTCP(0x798a23b1, 0x2826b928),
WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78292b8d, 0x2c1b3efb), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76a742d1, 0x3003ad85),
WTCP(0x75da14ef, 0x31f30638), WTCP(0x7504d345, 0x33def287), WTCP(0x74278c72, 0x35c750bc), WTCP(0x73424fa0, 0x37abff5d),
WTCP(0x72552c85, 0x398cdd32), WTCP(0x71603361, 0x3b69c947), WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x6f5f02b2, 0x3f1749b8),
WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6d3f4a40, 0x42b37e96), WTCP(0x6c242960, 0x447acd50), WTCP(0x6b019f1a, 0x463d6a87),
WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x68a69e81, 0x49b41533), WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x662eedc3, 0x4d168b8b),
WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x639b3a0b, 0x5063e008), WTCP(0x62471749, 0x520254ef), WTCP(0x60ec3830, 0x539b2af0),
WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5e22a487, 0x56bb8a90), WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5b3f42ae, 0x59c42381)
};
const PWord16 SineWindow112[56] =
{
WTCP(0x7fff31bf, 0x00e5c87e), WTCP(0x7ff8bfc7, 0x02b14de9), WTCP(0x7febdc2a, 0x047cb09e), WTCP(0x7fd8878e, 0x0647d97c),
WTCP(0x7fbec2ec, 0x0812b164), WTCP(0x7f9e8f91, 0x09dd213a), WTCP(0x7f77ef1c, 0x0ba711ea), WTCP(0x7f4ae37e, 0x0d706c64),
WTCP(0x7f176efc, 0x0f3919a0), WTCP(0x7edd942d, 0x110102a0), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e56b7a4, 0x148e2c22),
WTCP(0x7e09bcb4, 0x16533edc), WTCP(0x7db6690c, 0x181731cd), WTCP(0x7d5cc0df, 0x19d9ee32), WTCP(0x7cfcc8af, 0x1b9b5d5a),
WTCP(0x7c968552, 0x1d5b68a2), WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7bb731fb, 0x20d6f969), WTCP(0x7b3e2d40, 0x22925203),
WTCP(0x7abef3d5, 0x244becf6), WTCP(0x7a398c22, 0x2603b406), WTCP(0x79adfcdf, 0x27b9910e), WTCP(0x791c4d13, 0x296d6e00),
WTCP(0x78848414, 0x2b1f34eb), WTCP(0x77e6a986, 0x2ccecff7), WTCP(0x7742c55c, 0x2e7c2969), WTCP(0x7698dfd8, 0x30272ba0),
WTCP(0x75e90186, 0x31cfc11e), WTCP(0x75333343, 0x3375d481), WTCP(0x74777e35, 0x35195088), WTCP(0x73b5ebd1, 0x36ba2014),
WTCP(0x72ee85d5, 0x38582e27), WTCP(0x7221564d, 0x39f365e9), WTCP(0x714e678c, 0x3b8bb2a3), WTCP(0x7075c433, 0x3d20ffc8),
WTCP(0x6f977729, 0x3eb338ef), WTCP(0x6eb38ba1, 0x404249d5), WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6cdb0745, 0x4356a2ad),
WTCP(0x6be6863c, 0x44dbc2ec), WTCP(0x6aec9649, 0x465d6b89), WTCP(0x69ed4403, 0x47db8918), WTCP(0x68e89c43, 0x4956085b),
WTCP(0x67deac2c, 0x4accd644), WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x65bb28c7, 0x4daf12ba), WTCP(0x64a1b10b, 0x4f1a5c1a),
WTCP(0x6383281a, 0x5081a9c9), WTCP(0x625f9c5f, 0x51e4e9ae), WTCP(0x61371c8b, 0x534409e8), WTCP(0x6009b78a, 0x549ef8c6),
WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5da07af6, 0x5747fcca), WTCP(0x5c64c278, 0x5895efa4), WTCP(0x5b2462f5, 0x59df6c8f)
};
const PWord16 SineWindow120[60] =
{
WTCP(0x7fff4c54, 0x00d676eb), WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7fdd9dad, 0x05dcbcbe),
WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fab1d3d, 0x093516d4), WTCP(0x7f8975f9, 0x0ae0b22c), WTCP(0x7f62368f, 0x0c8bd35e),
WTCP(0x7f3560b9, 0x0e3667ad), WTCP(0x7f02f66f, 0x0fe05c64), WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e8d6d91, 0x13321c53),
WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7e01b096, 0x16807e15), WTCP(0x7db3860f, 0x18263d36), WTCP(0x7d5fd801, 0x19caed29),
WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7ca80038, 0x1d10d5c2), WTCP(0x7c43de8e, 0x1eb1e9a7), WTCP(0x7bda497d, 0x2051a4dd),
WTCP(0x7b6b45a5, 0x21eff528), WTCP(0x7af6d7e6, 0x238cc85d), WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x79fdd35c, 0x26c1af22),
WTCP(0x7979477d, 0x28599eb0), WTCP(0x78ef678f, 0x29efc925), WTCP(0x7860399e, 0x2b841caf), WTCP(0x77cbc3f2, 0x2d168792),
WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76931bae, 0x30355cdd), WTCP(0x75eef6ce, 0x31c1a43b), WTCP(0x7545a5a0, 0x334bbcde),
WTCP(0x74972f92, 0x34d3957e), WTCP(0x73e39c49, 0x36591cea), WTCP(0x732af3a7, 0x37dc420c), WTCP(0x726d3dc6, 0x395cf3e9),
WTCP(0x71aa82f7, 0x3adb21a1), WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x701620f5, 0x3dcfadb0), WTCP(0x6f448b7e, 0x3f45ead8),
WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6d92c59b, 0x422a0154), WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x6bcdc639, 0x45027c0c),
WTCP(0x6ae429ae, 0x466a36f9), WTCP(0x69f5dcd3, 0x47cedb31), WTCP(0x6902ea1d, 0x4930590f), WTCP(0x680b5c33, 0x4a8ea111),
WTCP(0x670f3df3, 0x4be9a3db), WTCP(0x660e9a6a, 0x4d415234), WTCP(0x65097cdb, 0x4e959d08), WTCP(0x63fff0ba, 0x4fe6756a),
WTCP(0x62f201ac, 0x5133cc94), WTCP(0x61dfbb8a, 0x527d93e6), WTCP(0x60c92a5a, 0x53c3bcea), WTCP(0x5fae5a55, 0x55063951),
WTCP(0x5e8f57e2, 0x5644faf4), WTCP(0x5d6c2f99, 0x577ff3da), WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5b19a0c8, 0x59ea5454),
};
const PWord16 SineWindow128[64] =
{
WTCP(0x7fff6216, 0x00c90f88), WTCP(0x7ffa72d1, 0x025b26d7), WTCP(0x7ff09478, 0x03ed26e6), WTCP(0x7fe1c76b, 0x057f0035),
WTCP(0x7fce0c3e, 0x0710a345), WTCP(0x7fb563b3, 0x08a2009a), WTCP(0x7f97cebd, 0x0a3308bd), WTCP(0x7f754e80, 0x0bc3ac35),
WTCP(0x7f4de451, 0x0d53db92), WTCP(0x7f2191b4, 0x0ee38766), WTCP(0x7ef05860, 0x1072a048), WTCP(0x7eba3a39, 0x120116d5),
WTCP(0x7e7f3957, 0x138edbb1), WTCP(0x7e3f57ff, 0x151bdf86), WTCP(0x7dfa98a8, 0x16a81305), WTCP(0x7db0fdf8, 0x183366e9),
WTCP(0x7d628ac6, 0x19bdcbf3), WTCP(0x7d0f4218, 0x1b4732ef), WTCP(0x7cb72724, 0x1ccf8cb3), WTCP(0x7c5a3d50, 0x1e56ca1e),
WTCP(0x7bf88830, 0x1fdcdc1b), WTCP(0x7b920b89, 0x2161b3a0), WTCP(0x7b26cb4f, 0x22e541af), WTCP(0x7ab6cba4, 0x24677758),
WTCP(0x7a4210d8, 0x25e845b6), WTCP(0x79c89f6e, 0x27679df4), WTCP(0x794a7c12, 0x28e5714b), WTCP(0x78c7aba2, 0x2a61b101),
WTCP(0x78403329, 0x2bdc4e6f), WTCP(0x77b417df, 0x2d553afc), WTCP(0x77235f2d, 0x2ecc681e), WTCP(0x768e0ea6, 0x3041c761),
WTCP(0x75f42c0b, 0x31b54a5e), WTCP(0x7555bd4c, 0x3326e2c3), WTCP(0x74b2c884, 0x34968250), WTCP(0x740b53fb, 0x36041ad9),
WTCP(0x735f6626, 0x376f9e46), WTCP(0x72af05a7, 0x38d8fe93), WTCP(0x71fa3949, 0x3a402dd2), WTCP(0x71410805, 0x3ba51e29),
WTCP(0x708378ff, 0x3d07c1d6), WTCP(0x6fc19385, 0x3e680b2c), WTCP(0x6efb5f12, 0x3fc5ec98), WTCP(0x6e30e34a, 0x4121589b),
WTCP(0x6d6227fa, 0x427a41d0), WTCP(0x6c8f351c, 0x43d09aed), WTCP(0x6bb812d1, 0x452456bd), WTCP(0x6adcc964, 0x46756828),
WTCP(0x69fd614a, 0x47c3c22f), WTCP(0x6919e320, 0x490f57ee), WTCP(0x683257ab, 0x4a581c9e), WTCP(0x6746c7d8, 0x4b9e0390),
WTCP(0x66573cbb, 0x4ce10034), WTCP(0x6563bf92, 0x4e210617), WTCP(0x646c59bf, 0x4f5e08e3), WTCP(0x637114cc, 0x5097fc5e),
WTCP(0x6271fa69, 0x51ced46e), WTCP(0x616f146c, 0x53028518), WTCP(0x60686ccf, 0x5433027d), WTCP(0x5f5e0db3, 0x556040e2),
WTCP(0x5e50015d, 0x568a34a9), WTCP(0x5d3e5237, 0x57b0d256), WTCP(0x5c290acc, 0x58d40e8c), WTCP(0x5b1035cf, 0x59f3de12),
};
const PWord16 SineWindow140[70] =
{
WTCP(0x7fff7bff, 0x00b7d3bc), WTCP(0x7ffb5c00, 0x02277547), WTCP(0x7ff31c25, 0x0397050d), WTCP(0x7fe6bcb0, 0x05067734),
WTCP(0x7fd63e09, 0x0675bfe7), WTCP(0x7fc1a0b6, 0x07e4d34d), WTCP(0x7fa8e564, 0x0953a594), WTCP(0x7f8c0cdc, 0x0ac22ae8),
WTCP(0x7f6b180f, 0x0c30577a), WTCP(0x7f46080a, 0x0d9e1f7d), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7eef9b46, 0x107852b2),
WTCP(0x7ebe414f, 0x11e4a65c), WTCP(0x7e88d1b4, 0x13506668), WTCP(0x7e4f4e2c, 0x14bb871b), WTCP(0x7e11b894, 0x1625fcc3),
WTCP(0x7dd012e6, 0x178fbbb1), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d409fe1, 0x1a60e6c3), WTCP(0x7cf2d72b, 0x1bc83baa),
WTCP(0x7ca1079d, 0x1d2eab5d), WTCP(0x7c4b33dc, 0x1e942a4d), WTCP(0x7bf15eac, 0x1ff8acf7), WTCP(0x7b938af1, 0x215c27dc),
WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7acbf416, 0x241fd88e), WTCP(0x7a623764, 0x257ff78e), WTCP(0x79f48904, 0x26dee12c),
WTCP(0x7982ec80, 0x283c8a1b), WTCP(0x790d6581, 0x2998e716), WTCP(0x7893f7d1, 0x2af3ece2), WTCP(0x7816a759, 0x2c4d9050),
WTCP(0x77957822, 0x2da5c63e), WTCP(0x77106e58, 0x2efc8393), WTCP(0x76878e43, 0x3051bd43), WTCP(0x75fadc4d, 0x31a56850),
WTCP(0x756a5cff, 0x32f779c7), WTCP(0x74d61500, 0x3447e6c3), WTCP(0x743e0918, 0x3596a46c), WTCP(0x73a23e2d, 0x36e3a7fa),
WTCP(0x7302b945, 0x382ee6b0), WTCP(0x725f7f84, 0x397855e1), WTCP(0x71b8962b, 0x3abfeaf1), WTCP(0x710e029e, 0x3c059b4f),
WTCP(0x705fca59, 0x3d495c7e), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6ef88241, 0x3fcae7a1), WTCP(0x6e3f7e01, 0x41089ce8),
WTCP(0x6d82ec32, 0x424439a6), WTCP(0x6cc2d2e9, 0x437db3b0), WTCP(0x6bff3855, 0x44b500eb), WTCP(0x6b3822c6, 0x45ea1750),
WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x699fa078, 0x484d77ce), WTCP(0x68ce40e4, 0x497bae33), WTCP(0x67f980a8, 0x4aa7865b),
WTCP(0x6721669f, 0x4bd0f69b), WTCP(0x6645f9c0, 0x4cf7f55d), WTCP(0x6567411d, 0x4e1c791f), WTCP(0x648543e4, 0x4f3e7875),
WTCP(0x63a0095c, 0x505dea05), WTCP(0x62b798ea, 0x517ac48c), WTCP(0x61cbfa0b, 0x5294fedd), WTCP(0x60dd3457, 0x53ac8fde),
WTCP(0x5feb4f7f, 0x54c16e8e), WTCP(0x5ef6534f, 0x55d391ff), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5d033497, 0x57ef83e9),
WTCP(0x5c052224, 0x58f940fa), WTCP(0x5b041885, 0x5a002001)
};
const PWord16 SineWindow160[80] =
{
WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ff62182, 0x03242abf), WTCP(0x7feca851, 0x0465b9aa),
WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fd03e23, 0x06e87c3f), WTCP(0x7fbd4dda, 0x0829a00c), WTCP(0x7fa736b4, 0x096a9049),
WTCP(0x7f8df93c, 0x0aab450d), WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f520de6, 0x0d2bdc80), WTCP(0x7f2f6183, 0x0e6baf61),
WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7eb48bfb, 0x1228e5f8), WTCP(0x7e85580c, 0x13671d3d),
WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7de50646, 0x171ec45c), WTCP(0x7da95d6c, 0x185ae269),
WTCP(0x7d6a9ad5, 0x199666a0), WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c9bc87a, 0x1d450a78),
WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7bb14ac5, 0x20ed2e7b), WTCP(0x7b5d039e, 0x2223a4c5),
WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7aab55ca, 0x248e02cb), WTCP(0x7a4df380, 0x25c1db44), WTCP(0x79ed8cad, 0x26f4c53e),
WTCP(0x798a23b1, 0x2826b928), WTCP(0x7923bb01, 0x2957af74), WTCP(0x78ba5524, 0x2a87a09d), WTCP(0x784df4b3, 0x2bb68522),
WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76f70f05, 0x2f3c9c40), WTCP(0x767edfbe, 0x306703bf),
WTCP(0x7603c3fd, 0x31903982), WTCP(0x7585becb, 0x32b83634), WTCP(0x7504d345, 0x33def287), WTCP(0x74810499, 0x35046736),
WTCP(0x73fa5607, 0x36288d03), WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x72e4668f, 0x386ccf2a), WTCP(0x72552c85, 0x398cdd32),
WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70969fca, 0x3ce465f3), WTCP(0x6ffc32eb, 0x3dfe9ba1),
WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6ebf12ff, 0x402e694c), WTCP(0x6e1c67c4, 0x4143f379), WTCP(0x6d770506, 0x4257e166),
WTCP(0x6cceeed8, 0x436a2c45), WTCP(0x6c242960, 0x447acd50), WTCP(0x6b76b8d6, 0x4589bdcf), WTCP(0x6ac6a180, 0x4696f710),
WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x68a69e81, 0x49b41533), WTCP(0x67ec1817, 0x4aba2f84),
WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x666f5ea6, 0x4cc0d5ae), WTCP(0x65ad3505, 0x4dc154bb), WTCP(0x64e88926, 0x4ebfe8a5),
WTCP(0x64215fe5, 0x4fbc8b22), WTCP(0x6357be2a, 0x50b735f8), WTCP(0x628ba8ef, 0x51afe2f6), WTCP(0x61bd253f, 0x52a68bfb),
WTCP(0x60ec3830, 0x539b2af0), WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5f4336a7, 0x557e3292), WTCP(0x5e6b2ca8, 0x566c8f55),
WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5bd529eb, 0x592ac2f7), WTCP(0x5af3eee6, 0x5a107561),
};
const PWord16 SineWindow180[90] =
{
WTCP(0x7fffb026, 0x008efa17), WTCP(0x7ffd3154, 0x01aceb7c), WTCP(0x7ff833bd, 0x02cad485), WTCP(0x7ff0b77a, 0x03e8af9e),
WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fda4391, 0x062425b6), WTCP(0x7fcb4c5b, 0x0741b592), WTCP(0x7fb9d759, 0x085f2137),
WTCP(0x7fa5e4e1, 0x097c6313), WTCP(0x7f8f7559, 0x0a997598), WTCP(0x7f76892f, 0x0bb65336), WTCP(0x7f5b20df, 0x0cd2f660),
WTCP(0x7f3d3cf4, 0x0def598a), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7efa04a8, 0x102749af), WTCP(0x7ed4b198, 0x1142cb98),
WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e82a146, 0x1378c774), WTCP(0x7e55e59e, 0x1493365f), WTCP(0x7e26b371, 0x15ad3e9a),
WTCP(0x7df50bab, 0x16c6daa6), WTCP(0x7dc0ef44, 0x17e00505), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d515caf, 0x1a10eed3),
WTCP(0x7d15e8ad, 0x1b28a351), WTCP(0x7cd80464, 0x1c3fd045), WTCP(0x7c97b109, 0x1d56703c), WTCP(0x7c54efdc, 0x1e6c7dc7),
WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7bc8294d, 0x2096cbf1), WTCP(0x7b7e26aa, 0x21ab01c0), WTCP(0x7b31bbb2, 0x22be8f87),
WTCP(0x7ae2e9e4, 0x23d16fe8), WTCP(0x7a91b2c7, 0x24e39d85), WTCP(0x7a3e17f2, 0x25f51307), WTCP(0x79e81b06, 0x2705cb19),
WTCP(0x798fbdb0, 0x2815c06a), WTCP(0x793501a9, 0x2924edac), WTCP(0x78d7e8b6, 0x2a334d96), WTCP(0x787874a7, 0x2b40dae2),
WTCP(0x7816a759, 0x2c4d9050), WTCP(0x77b282b3, 0x2d5968a3), WTCP(0x774c08ab, 0x2e645ea1), WTCP(0x76e33b3f, 0x2f6e6d16),
WTCP(0x76781c7a, 0x30778ed2), WTCP(0x760aae73, 0x317fbeab), WTCP(0x759af34c, 0x3286f779), WTCP(0x7528ed32, 0x338d341b),
WTCP(0x74b49e5f, 0x34926f74), WTCP(0x743e0918, 0x3596a46c), WTCP(0x73c52fab, 0x3699cdf2), WTCP(0x734a1475, 0x379be6f6),
WTCP(0x72ccb9db, 0x389cea72), WTCP(0x724d224f, 0x399cd362), WTCP(0x71cb504e, 0x3a9b9cca), WTCP(0x71474660, 0x3b9941b1),
WTCP(0x70c10718, 0x3c95bd26), WTCP(0x70389514, 0x3d910a3c), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6f212385, 0x3f8405bc),
WTCP(0x6e92296e, 0x407baa6a), WTCP(0x6e010780, 0x41720d46), WTCP(0x6d6dc08f, 0x42672981), WTCP(0x6cd8577a, 0x435afa54),
WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6ba72a98, 0x453ea6c7), WTCP(0x6b0b6cbd, 0x462e78f9), WTCP(0x6a6d98a4, 0x471cece7),
WTCP(0x69cdb162, 0x4809fdeb), WTCP(0x692bba14, 0x48f5a767), WTCP(0x6887b5e2, 0x49dfe4c2), WTCP(0x67e1a7ff, 0x4ac8b16b),
WTCP(0x673993a9, 0x4bb008d9), WTCP(0x668f7c25, 0x4c95e688), WTCP(0x65e364c4, 0x4d7a45fe), WTCP(0x653550e2, 0x4e5d22c6),
WTCP(0x648543e4, 0x4f3e7875), WTCP(0x63d34137, 0x501e42a5), WTCP(0x631f4c54, 0x50fc7cfb), WTCP(0x626968be, 0x51d92321),
WTCP(0x61b19a00, 0x52b430c9), WTCP(0x60f7e3b0, 0x538da1ae), WTCP(0x603c496c, 0x54657194), WTCP(0x5f7ecedd, 0x553b9c45),
WTCP(0x5ebf77b5, 0x56101d94), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5d3b428c, 0x57b41384), WTCP(0x5c766c1c, 0x58837ff4),
WTCP(0x5bafc837, 0x595132a2), WTCP(0x5ae75ab9, 0x5a1d278d),
};
const PWord16 SineWindow224[112] =
{
WTCP(0x7fffcc70, 0x0072e46e), WTCP(0x7ffe2fee, 0x0158abd6), WTCP(0x7ffaf6f1, 0x023e6ee8), WTCP(0x7ff62182, 0x03242abf),
WTCP(0x7fefafb1, 0x0409dc76), WTCP(0x7fe7a192, 0x04ef8129), WTCP(0x7fddf741, 0x05d515f5), WTCP(0x7fd2b0da, 0x06ba97f4),
WTCP(0x7fc5ce84, 0x07a00445), WTCP(0x7fb75068, 0x08855802), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f95819c, 0x0a4faa38),
WTCP(0x7f82315a, 0x0b34a2ec), WTCP(0x7f6d462b, 0x0c197784), WTCP(0x7f56c053, 0x0cfe251d), WTCP(0x7f3ea01a, 0x0de2a8d7),
WTCP(0x7f24e5cf, 0x0ec6ffd1), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7eeca451, 0x108f1c07), WTCP(0x7ece1dd3, 0x1172db86),
WTCP(0x7eadfeae, 0x125662c9), WTCP(0x7e8c4748, 0x1339aef3), WTCP(0x7e68f80e, 0x141cbd28), WTCP(0x7e441171, 0x14ff8a8c),
WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7df57ff3, 0x16c45777), WTCP(0x7dcbd60e, 0x17a6514a), WTCP(0x7da096c2, 0x1887fee6),
WTCP(0x7d73c299, 0x19695d74), WTCP(0x7d455a24, 0x1a4a6a1c), WTCP(0x7d155df9, 0x1b2b220b), WTCP(0x7ce3ceb2, 0x1c0b826a),
WTCP(0x7cb0acef, 0x1ceb8869), WTCP(0x7c7bf954, 0x1dcb3134), WTCP(0x7c45b48d, 0x1eaa79fa), WTCP(0x7c0ddf47, 0x1f895fed),
WTCP(0x7bd47a36, 0x2067e03e), WTCP(0x7b998614, 0x2145f81f), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b1ef397, 0x2300e366),
WTCP(0x7adf56c8, 0x23ddb139), WTCP(0x7a9e2dfd, 0x24ba0b76), WTCP(0x7a5b7a09, 0x2595ef56), WTCP(0x7a173bc2, 0x26715a16),
WTCP(0x79d17405, 0x274c48f2), WTCP(0x798a23b1, 0x2826b928), WTCP(0x79414bae, 0x2900a7f9), WTCP(0x78f6ece5, 0x29da12a7),
WTCP(0x78ab0847, 0x2ab2f674), WTCP(0x785d9ec8, 0x2b8b50a5), WTCP(0x780eb161, 0x2c631e82), WTCP(0x77be4111, 0x2d3a5d53),
WTCP(0x776c4edb, 0x2e110a62), WTCP(0x7718dbc8, 0x2ee722fb), WTCP(0x76c3e8e3, 0x2fbca46d), WTCP(0x766d773f, 0x30918c08),
WTCP(0x761587f3, 0x3165d71c), WTCP(0x75bc1c1a, 0x323982ff), WTCP(0x756134d4, 0x330c8d05), WTCP(0x7504d345, 0x33def287),
WTCP(0x74a6f899, 0x34b0b0df), WTCP(0x7447a5fc, 0x3581c569), WTCP(0x73e6dca3, 0x36522d83), WTCP(0x73849dc5, 0x3721e68d),
WTCP(0x7320ea9f, 0x37f0edea), WTCP(0x72bbc472, 0x38bf40ff), WTCP(0x72552c85, 0x398cdd32), WTCP(0x71ed2421, 0x3a59bfee),
WTCP(0x7183ac96, 0x3b25e69e), WTCP(0x7118c739, 0x3bf14eaf), WTCP(0x70ac7560, 0x3cbbf594), WTCP(0x703eb86a, 0x3d85d8bd),
WTCP(0x6fcf91b9, 0x3e4ef5a1), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6eed0cc0, 0x3fded27c), WTCP(0x6e79b152, 0x40a58d69),
WTCP(0x6e04f1dd, 0x416b7801), WTCP(0x6d8ecfd8, 0x42308fc4), WTCP(0x6d174cc0, 0x42f4d237), WTCP(0x6c9e6a16, 0x43b83ce3),
WTCP(0x6c242960, 0x447acd50), WTCP(0x6ba88c28, 0x453c810d), WTCP(0x6b2b93fd, 0x45fd55a9), WTCP(0x6aad4270, 0x46bd48b7),
WTCP(0x6a2d9919, 0x477c57cb), WTCP(0x69ac9994, 0x483a807f), WTCP(0x692a4580, 0x48f7c06d), WTCP(0x68a69e81, 0x49b41533),
WTCP(0x6821a640, 0x4a6f7c74), WTCP(0x679b5e68, 0x4b29f3d1), WTCP(0x6713c8ac, 0x4be378f4), WTCP(0x668ae6bf, 0x4c9c0985),
WTCP(0x6600ba5b, 0x4d53a332), WTCP(0x6575453d, 0x4e0a43ab), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x645a87dd, 0x4f748fd4),
WTCP(0x63cb432a, 0x502836f4), WTCP(0x633abcdc, 0x50dadbc1), WTCP(0x62a8f6c4, 0x518c7bfb), WTCP(0x6215f2b9, 0x523d1567),
WTCP(0x6181b292, 0x52eca5ca), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x60558573, 0x5448a2a5), WTCP(0x5fbd9c41, 0x54f50abb),
WTCP(0x5f247e83, 0x55a06106), WTCP(0x5e8a2e27, 0x564aa35d), WTCP(0x5deead1f, 0x56f3cf9d), WTCP(0x5d51fd5e, 0x579be3a4),
WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5c15199f, 0x58e8ba94), WTCP(0x5b74e99d, 0x598d794c), WTCP(0x5ad392de, 0x5a31176a)
};
const PWord16 SineWindow256[128] =
{
WTCP(0x7fffd886, 0x006487e3), WTCP(0x7ffe9cb2, 0x012d96b1), WTCP(0x7ffc250f, 0x01f6a297), WTCP(0x7ff871a2, 0x02bfa9a4),
WTCP(0x7ff38274, 0x0388a9ea), WTCP(0x7fed5791, 0x0451a177), WTCP(0x7fe5f108, 0x051a8e5c), WTCP(0x7fdd4eec, 0x05e36ea9),
WTCP(0x7fd37153, 0x06ac406f), WTCP(0x7fc85854, 0x077501be), WTCP(0x7fbc040a, 0x083db0a7), WTCP(0x7fae7495, 0x09064b3a),
WTCP(0x7f9faa15, 0x09cecf89), WTCP(0x7f8fa4b0, 0x0a973ba5), WTCP(0x7f7e648c, 0x0b5f8d9f), WTCP(0x7f6be9d4, 0x0c27c389),
WTCP(0x7f5834b7, 0x0cefdb76), WTCP(0x7f434563, 0x0db7d376), WTCP(0x7f2d1c0e, 0x0e7fa99e), WTCP(0x7f15b8ee, 0x0f475bff),
WTCP(0x7efd1c3c, 0x100ee8ad), WTCP(0x7ee34636, 0x10d64dbd), WTCP(0x7ec8371a, 0x119d8941), WTCP(0x7eabef2c, 0x1264994e),
WTCP(0x7e8e6eb2, 0x132b7bf9), WTCP(0x7e6fb5f4, 0x13f22f58), WTCP(0x7e4fc53e, 0x14b8b17f), WTCP(0x7e2e9cdf, 0x157f0086),
WTCP(0x7e0c3d29, 0x16451a83), WTCP(0x7de8a670, 0x170afd8d), WTCP(0x7dc3d90d, 0x17d0a7bc), WTCP(0x7d9dd55a, 0x18961728),
WTCP(0x7d769bb5, 0x195b49ea), WTCP(0x7d4e2c7f, 0x1a203e1b), WTCP(0x7d24881b, 0x1ae4f1d6), WTCP(0x7cf9aef0, 0x1ba96335),
WTCP(0x7ccda169, 0x1c6d9053), WTCP(0x7ca05ff1, 0x1d31774d), WTCP(0x7c71eaf9, 0x1df5163f), WTCP(0x7c4242f2, 0x1eb86b46),
WTCP(0x7c116853, 0x1f7b7481), WTCP(0x7bdf5b94, 0x203e300d), WTCP(0x7bac1d31, 0x21009c0c), WTCP(0x7b77ada8, 0x21c2b69c),
WTCP(0x7b420d7a, 0x22847de0), WTCP(0x7b0b3d2c, 0x2345eff8), WTCP(0x7ad33d45, 0x24070b08), WTCP(0x7a9a0e50, 0x24c7cd33),
WTCP(0x7a5fb0d8, 0x2588349d), WTCP(0x7a24256f, 0x26483f6c), WTCP(0x79e76ca7, 0x2707ebc7), WTCP(0x79a98715, 0x27c737d3),
WTCP(0x796a7554, 0x288621b9), WTCP(0x792a37fe, 0x2944a7a2), WTCP(0x78e8cfb2, 0x2a02c7b8), WTCP(0x78a63d11, 0x2ac08026),
WTCP(0x786280bf, 0x2b7dcf17), WTCP(0x781d9b65, 0x2c3ab2b9), WTCP(0x77d78daa, 0x2cf72939), WTCP(0x7790583e, 0x2db330c7),
WTCP(0x7747fbce, 0x2e6ec792), WTCP(0x76fe790e, 0x2f29ebcc), WTCP(0x76b3d0b4, 0x2fe49ba7), WTCP(0x76680376, 0x309ed556),
WTCP(0x761b1211, 0x3158970e), WTCP(0x75ccfd42, 0x3211df04), WTCP(0x757dc5ca, 0x32caab6f), WTCP(0x752d6c6c, 0x3382fa88),
WTCP(0x74dbf1ef, 0x343aca87), WTCP(0x7489571c, 0x34f219a8), WTCP(0x74359cbd, 0x35a8e625), WTCP(0x73e0c3a3, 0x365f2e3b),
WTCP(0x738acc9e, 0x3714f02a), WTCP(0x7333b883, 0x37ca2a30), WTCP(0x72db8828, 0x387eda8e), WTCP(0x72823c67, 0x3932ff87),
WTCP(0x7227d61c, 0x39e6975e), WTCP(0x71cc5626, 0x3a99a057), WTCP(0x716fbd68, 0x3b4c18ba), WTCP(0x71120cc5, 0x3bfdfecd),
WTCP(0x70b34525, 0x3caf50da), WTCP(0x70536771, 0x3d600d2c), WTCP(0x6ff27497, 0x3e10320d), WTCP(0x6f906d84, 0x3ebfbdcd),
WTCP(0x6f2d532c, 0x3f6eaeb8), WTCP(0x6ec92683, 0x401d0321), WTCP(0x6e63e87f, 0x40cab958), WTCP(0x6dfd9a1c, 0x4177cfb1),
WTCP(0x6d963c54, 0x42244481), WTCP(0x6d2dd027, 0x42d0161e), WTCP(0x6cc45698, 0x437b42e1), WTCP(0x6c59d0a9, 0x4425c923),
WTCP(0x6bee3f62, 0x44cfa740), WTCP(0x6b81a3cd, 0x4578db93), WTCP(0x6b13fef5, 0x4621647d), WTCP(0x6aa551e9, 0x46c9405c),
WTCP(0x6a359db9, 0x47706d93), WTCP(0x69c4e37a, 0x4816ea86), WTCP(0x69532442, 0x48bcb599), WTCP(0x68e06129, 0x4961cd33),
WTCP(0x686c9b4b, 0x4a062fbd), WTCP(0x67f7d3c5, 0x4aa9dba2), WTCP(0x67820bb7, 0x4b4ccf4d), WTCP(0x670b4444, 0x4bef092d),
WTCP(0x66937e91, 0x4c9087b1), WTCP(0x661abbc5, 0x4d31494b), WTCP(0x65a0fd0b, 0x4dd14c6e), WTCP(0x6526438f, 0x4e708f8f),
WTCP(0x64aa907f, 0x4f0f1126), WTCP(0x642de50d, 0x4faccfab), WTCP(0x63b0426d, 0x5049c999), WTCP(0x6331a9d4, 0x50e5fd6d),
WTCP(0x62b21c7b, 0x518169a5), WTCP(0x62319b9d, 0x521c0cc2), WTCP(0x61b02876, 0x52b5e546), WTCP(0x612dc447, 0x534ef1b5),
WTCP(0x60aa7050, 0x53e73097), WTCP(0x60262dd6, 0x547ea073), WTCP(0x5fa0fe1f, 0x55153fd4), WTCP(0x5f1ae274, 0x55ab0d46),
WTCP(0x5e93dc1f, 0x56400758), WTCP(0x5e0bec6e, 0x56d42c99), WTCP(0x5d8314b1, 0x57677b9d), WTCP(0x5cf95638, 0x57f9f2f8),
WTCP(0x5c6eb258, 0x588b9140), WTCP(0x5be32a67, 0x591c550e), WTCP(0x5b56bfbd, 0x59ac3cfd), WTCP(0x5ac973b5, 0x5a3b47ab),
};
const PWord16 SineWindow280[140] =
{
WTCP(0x7fffdf00, 0x005be9f6), WTCP(0x7ffed6ff, 0x0113bd23), WTCP(0x7ffcc6ff, 0x01cb8e18), WTCP(0x7ff9af04, 0x02835b5a),
WTCP(0x7ff58f15, 0x033b236c), WTCP(0x7ff0673a, 0x03f2e4d4), WTCP(0x7fea377e, 0x04aa9e17), WTCP(0x7fe2ffee, 0x05624dba),
WTCP(0x7fdac098, 0x0619f243), WTCP(0x7fd1798e, 0x06d18a36), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fbbd4aa, 0x08408e70),
WTCP(0x7faf76fe, 0x08f7f7c3), WTCP(0x7fa211f6, 0x09af4e96), WTCP(0x7f93a5af, 0x0a66916f), WTCP(0x7f843246, 0x0b1dbed5),
WTCP(0x7f73b7da, 0x0bd4d54d), WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7f4fae88, 0x0d42b78f), WTCP(0x7f3c1fec, 0x0df98066),
WTCP(0x7f278ae1, 0x0eb02c6a), WTCP(0x7f11ef95, 0x0f66ba22), WTCP(0x7efb4e31, 0x101d2817), WTCP(0x7ee3a6e7, 0x10d374cf),
WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7eb1475f, 0x123fa4ab), WTCP(0x7e968f8b, 0x12f584e0), WTCP(0x7e7ad29e, 0x13ab3dfa),
WTCP(0x7e5e10d3, 0x1460ce82), WTCP(0x7e404a65, 0x15163503), WTCP(0x7e217f90, 0x15cb7006), WTCP(0x7e01b096, 0x16807e15),
WTCP(0x7de0ddb6, 0x17355dba), WTCP(0x7dbf0736, 0x17ea0d81), WTCP(0x7d9c2d5a, 0x189e8bf6), WTCP(0x7d78506a, 0x1952d7a3),
WTCP(0x7d5370b2, 0x1a06ef15), WTCP(0x7d2d8e7b, 0x1abad0d8), WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7cdec3d2, 0x1c21ed87),
WTCP(0x7cb5dc00, 0x1cd5258f), WTCP(0x7c8bf2f7, 0x1d88221e), WTCP(0x7c61090b, 0x1e3ae1c5), WTCP(0x7c351e96, 0x1eed6311),
WTCP(0x7c0833f3, 0x1f9fa494), WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7bab5f93, 0x2103627d), WTCP(0x7b7b7697, 0x21b4dc06),
WTCP(0x7b4a8eeb, 0x2266100a), WTCP(0x7b18a8f4, 0x2316fd1b), WTCP(0x7ae5c518, 0x23c7a1cc), WTCP(0x7ab1e3c2, 0x2477fcb1),
WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x7a472a51, 0x25d7cf68), WTCP(0x7a105313, 0x26874464), WTCP(0x79d88013, 0x273669e9),
WTCP(0x799fb1c2, 0x27e53e8e), WTCP(0x7965e897, 0x2893c0e9), WTCP(0x792b2508, 0x2941ef93), WTCP(0x78ef678f, 0x29efc925),
WTCP(0x78b2b0a7, 0x2a9d4c38), WTCP(0x787500ce, 0x2b4a7766), WTCP(0x78365881, 0x2bf7494a), WTCP(0x77f6b844, 0x2ca3c07f),
WTCP(0x77b62098, 0x2d4fdba2), WTCP(0x77749203, 0x2dfb9950), WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76ee923e, 0x2f51f6c4),
WTCP(0x76aa2222, 0x2ffc93c9), WTCP(0x7664bd46, 0x30a6cdd3), WTCP(0x761e6439, 0x3150a385), WTCP(0x75d7178c, 0x31fa1381),
WTCP(0x758ed7d2, 0x32a31c68), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x74fb818e, 0x33f3f387), WTCP(0x74b06c33, 0x349bbf09),
WTCP(0x7464662c, 0x35431e09), WTCP(0x74177014, 0x35ea0f2e), WTCP(0x73c98a8a, 0x36909120), WTCP(0x737ab630, 0x3736a287),
WTCP(0x732af3a7, 0x37dc420c), WTCP(0x72da4395, 0x38816e5b), WTCP(0x7288a69f, 0x3926261e), WTCP(0x72361d6e, 0x39ca6802),
WTCP(0x71e2a8ad, 0x3a6e32b4), WTCP(0x718e4907, 0x3b1184e2), WTCP(0x7138ff2a, 0x3bb45d3b), WTCP(0x70e2cbc6, 0x3c56ba70),
WTCP(0x708baf8d, 0x3cf89b31), WTCP(0x7033ab34, 0x3d99fe31), WTCP(0x6fdabf6e, 0x3e3ae223), WTCP(0x6f80ecf4, 0x3edb45ba),
WTCP(0x6f26347f, 0x3f7b27ac), WTCP(0x6eca96ca, 0x401a86b0), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6e10ae96, 0x4157b6ca),
WTCP(0x6db26597, 0x41f58552), WTCP(0x6d533a56, 0x4292cbcf), WTCP(0x6cf32d99, 0x432f88fc), WTCP(0x6c924024, 0x43cbbb97),
WTCP(0x6c3072c1, 0x4467625d), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6b6a3b58, 0x459d0766), WTCP(0x6b05d2ea, 0x4637032c),
WTCP(0x6aa08dbf, 0x46d06e1f), WTCP(0x6a3a6ca8, 0x47694703), WTCP(0x69d37078, 0x48018c9e), WTCP(0x696b9a02, 0x48993db5),
WTCP(0x6902ea1d, 0x4930590f), WTCP(0x689961a1, 0x49c6dd74), WTCP(0x682f0167, 0x4a5cc9af), WTCP(0x67c3ca4c, 0x4af21c89),
WTCP(0x6757bd2b, 0x4b86d4cf), WTCP(0x66eadae5, 0x4c1af14f), WTCP(0x667d2459, 0x4cae70d6), WTCP(0x660e9a6a, 0x4d415234),
WTCP(0x659f3dfc, 0x4dd3943b), WTCP(0x652f0ff4, 0x4e6535bd), WTCP(0x64be113a, 0x4ef6358d), WTCP(0x644c42b8, 0x4f869280),
WTCP(0x63d9a556, 0x50164b6d), WTCP(0x63663a03, 0x50a55f2c), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x627cfd41, 0x51c19281),
WTCP(0x62072db3, 0x524eafce), WTCP(0x619093f5, 0x52db2357), WTCP(0x611930fc, 0x5366ebfc), WTCP(0x60a105be, 0x53f2089b),
WTCP(0x60281333, 0x547c7817), WTCP(0x5fae5a55, 0x55063951), WTCP(0x5f33dc1d, 0x558f4b2d), WTCP(0x5eb8998a, 0x5617ac90),
WTCP(0x5e3c9399, 0x569f5c62), WTCP(0x5dbfcb4a, 0x5726598b), WTCP(0x5d42419f, 0x57aca2f3), WTCP(0x5cc3f79a, 0x58323787),
WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5bc52696, 0x593b3de2), WTCP(0x5b44a1a5, 0x59bead87), WTCP(0x5ac36076, 0x5a416413)
};
const PWord16 SineWindow320[160] =
{
WTCP(0x7fffe6bc, 0x00506cb9), WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7ffb29fd, 0x0232f21a),
WTCP(0x7ff80186, 0x02d3c39b), WTCP(0x7ff40efa, 0x037490a5), WTCP(0x7fef5260, 0x0415583b), WTCP(0x7fe9cbc0, 0x04b6195d),
WTCP(0x7fe37b22, 0x0556d30f), WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd47c14, 0x06982c2b), WTCP(0x7fcbcdbc, 0x0738c998),
WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fad081b, 0x091a597e), WTCP(0x7fa132e8, 0x09bac35d),
WTCP(0x7f949429, 0x0a5b1dde), WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f78fa5b, 0x0b9ba0d5), WTCP(0x7f69ff76, 0x0c3bc74f),
WTCP(0x7f5a3b5e, 0x0cdbda79), WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7f2638db, 0x0ebb962c),
WTCP(0x7f1350f8, 0x0f5b5231), WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7eeb274d, 0x109a807e), WTCP(0x7ed5e5c6, 0x1139f0cf),
WTCP(0x7ebfdbf5, 0x11d945eb), WTCP(0x7ea909fc, 0x12787ed8), WTCP(0x7e917000, 0x13179a9b), WTCP(0x7e790e25, 0x13b69836),
WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e2b3ae8, 0x1592d257), WTCP(0x7e0fbb22, 0x16314d8e),
WTCP(0x7df3744b, 0x16cfa5b9), WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7db8921c, 0x180be904), WTCP(0x7d99f721, 0x18a9d231),
WTCP(0x7d7a95cf, 0x1947946c), WTCP(0x7d5a6e57, 0x19e52ebb), WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7d17cdc2, 0x1b1fe7b3),
WTCP(0x7cf5550e, 0x1bbd046c), WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cae13e4, 0x1cf6b97c), WTCP(0x7c894bde, 0x1d934fe5),
WTCP(0x7c63bf2f, 0x1e2fb79a), WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c1658c5, 0x1f67f70b), WTCP(0x7bee7f85, 0x2003ccdb),
WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7b9c8226, 0x213adfda), WTCP(0x7b725e8a, 0x21d61b1e), WTCP(0x7b4777fe, 0x227120f3),
WTCP(0x7b1bcec4, 0x230bf065), WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ac23561, 0x2440e84d), WTCP(0x7a9445c5, 0x24db0edb),
WTCP(0x7a659496, 0x2574fb36), WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a05eead, 0x26a82186), WTCP(0x79d4fa89, 0x27415996),
WTCP(0x79a34602, 0x27da53a9), WTCP(0x7970d165, 0x28730ecd), WTCP(0x793d9d03, 0x290b8a12), WTCP(0x7909a92d, 0x29a3c485),
WTCP(0x78d4f634, 0x2a3bbd37), WTCP(0x789f846b, 0x2ad37338), WTCP(0x78695428, 0x2b6ae598), WTCP(0x783265c0, 0x2c021369),
WTCP(0x77fab989, 0x2c98fbba), WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77892910, 0x2dc5f829), WTCP(0x774f4581, 0x2e5c0a6b),
WTCP(0x7714a58b, 0x2ef1d377), WTCP(0x76d94989, 0x2f875262), WTCP(0x769d31d9, 0x301c863f), WTCP(0x76605edb, 0x30b16e23),
WTCP(0x7622d0ef, 0x31460922), WTCP(0x75e48874, 0x31da5651), WTCP(0x75a585cf, 0x326e54c7), WTCP(0x7565c962, 0x3302039b),
WTCP(0x75255392, 0x339561e1), WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74a23d62, 0x34bb2927), WTCP(0x745f9dd1, 0x354d9057),
WTCP(0x741c467b, 0x35dfa35a), WTCP(0x73d837ca, 0x3671614b), WTCP(0x7393722a, 0x3702c942), WTCP(0x734df607, 0x3793da5b),
WTCP(0x7307c3d0, 0x382493b0), WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72793edf, 0x3944fb7e), WTCP(0x7230ed07, 0x39d4a82f),
WTCP(0x71e7e6dc, 0x3a63f98d), WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x7153bf5d, 0x3b8186ca), WTCP(0x71089ef2, 0x3c0fc0e6),
WTCP(0x70bccc09, 0x3c9d9c28), WTCP(0x70704718, 0x3d2b17b3), WTCP(0x7023109a, 0x3db832a6), WTCP(0x6fd52907, 0x3e44ec22),
WTCP(0x6f8690db, 0x3ed14349), WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6ee750a8, 0x3fe8c724), WTCP(0x6e96a99d, 0x4073f21d),
WTCP(0x6e4553ef, 0x40feb74f), WTCP(0x6df35020, 0x418915de), WTCP(0x6da09eb1, 0x42130cf0), WTCP(0x6d4d4023, 0x429c9bab),
WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6ca47dbf, 0x43ae7cb7), WTCP(0x6c4f1af2, 0x4436cd58), WTCP(0x6bf90d1d, 0x44beb240),
WTCP(0x6ba254c7, 0x45462a9a), WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6af2e6bc, 0x4653d24b), WTCP(0x6a9a321d, 0x46d9fff8),
WTCP(0x6a40d527, 0x475fbdc3), WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x698c246c, 0x4869e665), WTCP(0x6930d1c4, 0x48ee4f98),
WTCP(0x68d4d900, 0x497245a1), WTCP(0x68783ab1, 0x49f5c7ae), WTCP(0x681af76a, 0x4a78d4f0), WTCP(0x67bd0fbd, 0x4afb6c98),
WTCP(0x675e843e, 0x4b7d8dd8), WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x669f8425, 0x4c8069ea), WTCP(0x663f10b7, 0x4d012324),
WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x657c4613, 0x4e012800), WTCP(0x6519f010, 0x4e80720e), WTCP(0x64b6fa66, 0x4eff4025),
WTCP(0x645365b2, 0x4f7d917c), WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x638a619e, 0x5078bad1), WTCP(0x6324f37d, 0x50f59141),
WTCP(0x62bee8cc, 0x5171e7d9), WTCP(0x6258422c, 0x51edbdd4), WTCP(0x61f1003f, 0x5269126e), WTCP(0x618923a9, 0x52e3e4e6),
WTCP(0x6120ad0d, 0x535e3479), WTCP(0x60b79d10, 0x53d80065), WTCP(0x604df459, 0x545147eb), WTCP(0x5fe3b38d, 0x54ca0a4b),
WTCP(0x5f78db56, 0x554246c6), WTCP(0x5f0d6c5b, 0x55b9fc9e), WTCP(0x5ea16747, 0x56312b17), WTCP(0x5e34ccc3, 0x56a7d174),
WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5ceb8355, 0x58088c96), WTCP(0x5c7c99d1, 0x587d0b3b),
WTCP(0x5c0d1e41, 0x58f0fe23), WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b2c73bb, 0x59d73de3), WTCP(0x5abb4629, 0x5a498950),
};
const PWord16 SineWindow420[210] =
{
WTCP(0x7ffff155, 0x003d46a7), WTCP(0x7fff7bff, 0x00b7d3bc), WTCP(0x7ffe9154, 0x01326029), WTCP(0x7ffd3154, 0x01aceb7c),
WTCP(0x7ffb5c00, 0x02277547), WTCP(0x7ff9115b, 0x02a1fd18), WTCP(0x7ff65166, 0x031c8280), WTCP(0x7ff31c25, 0x0397050d),
WTCP(0x7fef7199, 0x0411844f), WTCP(0x7feb51c6, 0x048bffd7), WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fe1b25b, 0x0580e9f6),
WTCP(0x7fdc32cc, 0x05fb57ac), WTCP(0x7fd63e09, 0x0675bfe7), WTCP(0x7fcfd415, 0x06f02235), WTCP(0x7fc8f4f7, 0x076a7e27),
WTCP(0x7fc1a0b6, 0x07e4d34d), WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7fb198e5, 0x08d96773), WTCP(0x7fa8e564, 0x0953a594),
WTCP(0x7f9fbcdc, 0x09cddb27), WTCP(0x7f961f57, 0x0a4807be), WTCP(0x7f8c0cdc, 0x0ac22ae8), WTCP(0x7f818577, 0x0b3c4435),
WTCP(0x7f76892f, 0x0bb65336), WTCP(0x7f6b180f, 0x0c30577a), WTCP(0x7f5f3221, 0x0caa5092), WTCP(0x7f52d771, 0x0d243e0d),
WTCP(0x7f46080a, 0x0d9e1f7d), WTCP(0x7f38c3f7, 0x0e17f471), WTCP(0x7f2b0b45, 0x0e91bc79), WTCP(0x7f1cde01, 0x0f0b7727),
WTCP(0x7f0e3c36, 0x0f85240a), WTCP(0x7eff25f3, 0x0ffec2b3), WTCP(0x7eef9b46, 0x107852b2), WTCP(0x7edf9c3c, 0x10f1d398),
WTCP(0x7ecf28e5, 0x116b44f6), WTCP(0x7ebe414f, 0x11e4a65c), WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e9b15a6, 0x12d73784),
WTCP(0x7e88d1b4, 0x13506668), WTCP(0x7e7619c3, 0x13c98397), WTCP(0x7e62ede5, 0x14428ea2), WTCP(0x7e4f4e2c, 0x14bb871b),
WTCP(0x7e3b3aaa, 0x15346c93), WTCP(0x7e26b371, 0x15ad3e9a), WTCP(0x7e11b894, 0x1625fcc3), WTCP(0x7dfc4a26, 0x169ea69e),
WTCP(0x7de6683a, 0x17173bbd), WTCP(0x7dd012e6, 0x178fbbb1), WTCP(0x7db94a3c, 0x1808260c), WTCP(0x7da20e53, 0x18807a5f),
WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d723d18, 0x1970df36), WTCP(0x7d59a7f1, 0x19e8eedd), WTCP(0x7d409fe1, 0x1a60e6c3),
WTCP(0x7d272501, 0x1ad8c67c), WTCP(0x7d0d3767, 0x1b508d98), WTCP(0x7cf2d72b, 0x1bc83baa), WTCP(0x7cd80464, 0x1c3fd045),
WTCP(0x7cbcbf2d, 0x1cb74afa), WTCP(0x7ca1079d, 0x1d2eab5d), WTCP(0x7c84ddcf, 0x1da5f0ff), WTCP(0x7c6841db, 0x1e1d1b73),
WTCP(0x7c4b33dc, 0x1e942a4d), WTCP(0x7c2db3ee, 0x1f0b1d1f), WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7bf15eac, 0x1ff8acf7),
WTCP(0x7bd28991, 0x206f4923), WTCP(0x7bb342f3, 0x20e5c793), WTCP(0x7b938af1, 0x215c27dc), WTCP(0x7b7361a7, 0x21d2698f),
WTCP(0x7b52c733, 0x22488c42), WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7b103f43, 0x233472f3), WTCP(0x7aee5205, 0x23aa361a),
WTCP(0x7acbf416, 0x241fd88e), WTCP(0x7aa92596, 0x249559e6), WTCP(0x7a85e6a5, 0x250ab9b4), WTCP(0x7a623764, 0x257ff78e),
WTCP(0x7a3e17f2, 0x25f51307), WTCP(0x7a198872, 0x266a0bb5), WTCP(0x79f48904, 0x26dee12c), WTCP(0x79cf19cb, 0x27539302),
WTCP(0x79a93ae9, 0x27c820ca), WTCP(0x7982ec80, 0x283c8a1b), WTCP(0x795c2eb5, 0x28b0ce8a), WTCP(0x793501a9, 0x2924edac),
WTCP(0x790d6581, 0x2998e716), WTCP(0x78e55a62, 0x2a0cba5e), WTCP(0x78bce070, 0x2a80671b), WTCP(0x7893f7d1, 0x2af3ece2),
WTCP(0x786aa0a9, 0x2b674b49), WTCP(0x7840db1f, 0x2bda81e6), WTCP(0x7816a759, 0x2c4d9050), WTCP(0x77ec057d, 0x2cc0761e),
WTCP(0x77c0f5b3, 0x2d3332e5), WTCP(0x77957822, 0x2da5c63e), WTCP(0x77698cf3, 0x2e182fbe), WTCP(0x773d344d, 0x2e8a6efd),
WTCP(0x77106e58, 0x2efc8393), WTCP(0x76e33b3f, 0x2f6e6d16), WTCP(0x76b59b2a, 0x2fe02b1e), WTCP(0x76878e43, 0x3051bd43),
WTCP(0x765914b5, 0x30c3231d), WTCP(0x762a2eaa, 0x31345c44), WTCP(0x75fadc4d, 0x31a56850), WTCP(0x75cb1dca, 0x321646d9),
WTCP(0x759af34c, 0x3286f779), WTCP(0x756a5cff, 0x32f779c7), WTCP(0x75395b10, 0x3367cd5d), WTCP(0x7507edac, 0x33d7f1d3),
WTCP(0x74d61500, 0x3447e6c3), WTCP(0x74a3d13a, 0x34b7abc6), WTCP(0x74712288, 0x35274076), WTCP(0x743e0918, 0x3596a46c),
WTCP(0x740a8519, 0x3605d743), WTCP(0x73d696bb, 0x3674d894), WTCP(0x73a23e2d, 0x36e3a7fa), WTCP(0x736d7b9f, 0x3752450f),
WTCP(0x73384f41, 0x37c0af6d), WTCP(0x7302b945, 0x382ee6b0), WTCP(0x72ccb9db, 0x389cea72), WTCP(0x72965134, 0x390aba4f),
WTCP(0x725f7f84, 0x397855e1), WTCP(0x722844fb, 0x39e5bcc5), WTCP(0x71f0a1cc, 0x3a52ee96), WTCP(0x71b8962b, 0x3abfeaf1),
WTCP(0x7180224b, 0x3b2cb170), WTCP(0x71474660, 0x3b9941b1), WTCP(0x710e029e, 0x3c059b4f), WTCP(0x70d45738, 0x3c71bde8),
WTCP(0x709a4465, 0x3cdda919), WTCP(0x705fca59, 0x3d495c7e), WTCP(0x7024e94b, 0x3db4d7b5), WTCP(0x6fe9a16f, 0x3e201a5b),
WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6f71de2a, 0x3ef5f46c), WTCP(0x6f35632e, 0x3f608b13), WTCP(0x6ef88241, 0x3fcae7a1),
WTCP(0x6ebb3b9a, 0x403509b4), WTCP(0x6e7d8f72, 0x409ef0ed), WTCP(0x6e3f7e01, 0x41089ce8), WTCP(0x6e010780, 0x41720d46),
WTCP(0x6dc22c28, 0x41db41a5), WTCP(0x6d82ec32, 0x424439a6), WTCP(0x6d4347da, 0x42acf4e8), WTCP(0x6d033f58, 0x4315730c),
WTCP(0x6cc2d2e9, 0x437db3b0), WTCP(0x6c8202c6, 0x43e5b676), WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6bff3855, 0x44b500eb),
WTCP(0x6bbd3e7f, 0x451c47dc), WTCP(0x6b7ae1e6, 0x45834f72), WTCP(0x6b3822c6, 0x45ea1750), WTCP(0x6af5015c, 0x46509f16),
WTCP(0x6ab17de7, 0x46b6e668), WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x6a2951d2, 0x4782b236), WTCP(0x69e4a9ae, 0x47e835f7),
WTCP(0x699fa078, 0x484d77ce), WTCP(0x695a366f, 0x48b2775d), WTCP(0x69146bd3, 0x49173448), WTCP(0x68ce40e4, 0x497bae33),
WTCP(0x6887b5e2, 0x49dfe4c2), WTCP(0x6840cb0e, 0x4a43d799), WTCP(0x67f980a8, 0x4aa7865b), WTCP(0x67b1d6f3, 0x4b0af0ae),
WTCP(0x6769ce2f, 0x4b6e1637), WTCP(0x6721669f, 0x4bd0f69b), WTCP(0x66d8a085, 0x4c33917f), WTCP(0x668f7c25, 0x4c95e688),
WTCP(0x6645f9c0, 0x4cf7f55d), WTCP(0x65fc199a, 0x4d59bda3), WTCP(0x65b1dbf8, 0x4dbb3f02), WTCP(0x6567411d, 0x4e1c791f),
WTCP(0x651c494d, 0x4e7d6ba2), WTCP(0x64d0f4ce, 0x4ede1631), WTCP(0x648543e4, 0x4f3e7875), WTCP(0x643936d4, 0x4f9e9214),
WTCP(0x63eccde5, 0x4ffe62b6), WTCP(0x63a0095c, 0x505dea05), WTCP(0x6352e980, 0x50bd27a7), WTCP(0x63056e98, 0x511c1b47),
WTCP(0x62b798ea, 0x517ac48c), WTCP(0x626968be, 0x51d92321), WTCP(0x621ade5c, 0x523736ae), WTCP(0x61cbfa0b, 0x5294fedd),
WTCP(0x617cbc14, 0x52f27b58), WTCP(0x612d24c0, 0x534fabcb), WTCP(0x60dd3457, 0x53ac8fde), WTCP(0x608ceb22, 0x5409273e),
WTCP(0x603c496c, 0x54657194), WTCP(0x5feb4f7f, 0x54c16e8e), WTCP(0x5f99fda4, 0x551d1dd5), WTCP(0x5f485426, 0x55787f17),
WTCP(0x5ef6534f, 0x55d391ff), WTCP(0x5ea3fb6c, 0x562e563a), WTCP(0x5e514cc8, 0x5688cb75), WTCP(0x5dfe47ad, 0x56e2f15d),
WTCP(0x5daaec6a, 0x573cc79f), WTCP(0x5d573b49, 0x57964de9), WTCP(0x5d033497, 0x57ef83e9), WTCP(0x5caed8a2, 0x5848694d),
WTCP(0x5c5a27b8, 0x58a0fdc3), WTCP(0x5c052224, 0x58f940fa), WTCP(0x5bafc837, 0x595132a2), WTCP(0x5b5a1a3d, 0x59a8d26a),
WTCP(0x5b041885, 0x5a002001), WTCP(0x5aadc35e, 0x5a571b18)
};
/**
* \brief Helper table containing the length, rasterand shape mapping to individual window slope tables.
* [0: sine ][0: radix2 raster ][ceil(log2(length)) length 4 .. 1024 ]
* [1: 640 raster
*/
const PWord16 *const windowSlopes[1][2][8] =
{
{ /* Sine */
{ /* Radix 2 */
NULL,
NULL,
SineWindow16,
SineWindow32,
SineWindow64,
SineWindow128,
SineWindow256,
NULL
},
{ /* 640 raster */
NULL, /* 2.5 */
NULL, /* 5 */
SineWindow10,
SineWindow20,
SineWindow40,
SineWindow80,
SineWindow160,
SineWindow320
},
}
};
#define DCTIV_SINETABLE SineTable512
#define DCTIV_SINETABLE_SIZE_LD 9
#define DCTIV_SINETABLE320 SineTable320
#define DCTIV_SINETABLE320_SIZE_LD 8
void BASOP_getTables(const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *psin_step, Word16 length)
{
const PWord16 *twiddle;
const PWord16 *sine;
Word16 ld2_length, sin_step;
/* Get ld2 of length - 2 + 1
-2: because first table entry is window of size 4
+1: because we already include +1 because of ceil(log2(length)) */
ld2_length = sub(16 -1 -1, norm_s(length));
/* Extract sort of "eigenvalue" (the 5 left most bits) of length. */
SWITCH ( (unsigned short)lshl(length, sub(15, ld2_length) ) )
{
case 0xa000: /* 640 */
move16();
move16();
sine = DCTIV_SINETABLE320;
sin_step = shl(1, sub(DCTIV_SINETABLE320_SIZE_LD+1, ld2_length));
twiddle = windowSlopes[0][1][sub(ld2_length,1)];
BREAK;
case 0x8000: /* radix 2 */
move16();
move16();
sine = DCTIV_SINETABLE;
sin_step = shl(1, sub(DCTIV_SINETABLE_SIZE_LD+1, ld2_length));
twiddle = windowSlopes[0][0][sub(ld2_length,2)];
BREAK;
default: /* not instrumented, probably obsolete */
sine = NULL;
sin_step = 0;
twiddle = NULL;
BREAK;
}
if (ptwiddle != NULL)
{
assert(twiddle != NULL || length == 0);
move16();
*ptwiddle = twiddle;
}
if (sin_twiddle != NULL)
{
move16();
*sin_twiddle = sine;
}
if ( psin_step != NULL )
{
assert(sin_step > 0 || length == 0);
move16();
*psin_step = sin_step;
}
}
const PWord16* getSineWindowTable(Word16 length)
{
const PWord16 *p = NULL;
switch (length)
{
case 10:
p = SineWindow10;
BREAK;
case 16:
p = SineWindow16;
BREAK;
case 20:
p = SineWindow20;
BREAK;
case 30:
p = SineWindow30;
BREAK;
case 32:
p = SineWindow32;
BREAK;
case 40:
p = SineWindow40;
BREAK;
case 48:
p = SineWindow48;
BREAK;
case 60:
p = SineWindow60;
BREAK;
case 70:
p = SineWindow70;
BREAK;
case 96:
p = SineWindow96;
BREAK;
case 112:
p = SineWindow112;
BREAK;
case 120:
p = SineWindow120;
BREAK;
case 140:
p = SineWindow140;
BREAK;
case 180:
p = SineWindow180;
BREAK;
case 224:
p = SineWindow224;
BREAK;
case 280:
p = SineWindow280;
BREAK;
case 420:
p = SineWindow420;
BREAK;
}
assert(p != NULL);
return p;
}
+81
View File
@@ -0,0 +1,81 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef __BASOP_UTIL_ROM_H__
#define __BASOP_UTIL_ROM_H__
#include "typedef.h"
#include "basop_util.h"
#define LD_INT_TAB_LEN 120
#define INV_TABLE_SIZE 256
#define SQRT_TABLE_SIZE 256
#ifndef CHEAP_NORM_SIZE
#define CHEAP_NORM_SIZE 161
#endif
#define MINSFTAB 7
#define MAXSFTAB 25
/**
* \brief Lookup-Table for binary logarithm
*/
extern const Word16 ldCoeff[7];
/**
\brief Lookup-Table for binary power algorithm
*/
extern const UWord32 exp2_tab_long[32];
/**
\brief Lookup-Table for binary power algorithm
*/
extern const UWord32 exp2w_tab_long[32];
/**
\brief Lookup-Table for binary power algorithm
*/
extern const UWord32 exp2x_tab_long[32];
/**
\brief Lookup-Table for integer binary logarithm
*/
extern const Word32 ldIntCoeff[LD_INT_TAB_LEN];
/**
* \brief Lookup-Table for 1/x
*/
extern const Word16 invTable[INV_TABLE_SIZE+1];
/**
* \brief 1/x, x=[0,1,2,3...] table
*/
extern const Word16 InvIntTable[65];
/**
* \brief Lookup-Table for Squareroot
*/
extern const Word16 sqrtTable[SQRT_TABLE_SIZE+1];
extern const Word16 invSqrtTable[SQRT_TABLE_SIZE+1];
extern const Word32 BASOP_util_normReciprocal[CHEAP_NORM_SIZE];
extern const Word16 f_atan_expand_range[MAXSFTAB-(MINSFTAB-1)];
/**
* \ brief Sine table
*/
extern const PWord16 SineTable512[257];
extern const PWord16 SineTable480[241];
extern const PWord16 SineTable400[201];
extern const PWord16 SineTable384[193];
extern const PWord16 SineTable320[161];
/**
* \ brief Lookup for sine tables and windows.
*/
void BASOP_getTables(const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *sin_step, Word16 length);
const PWord16* getSineWindowTable(Word16 length);
#endif
+21498
View File
File diff suppressed because it is too large Load Diff
+1250
View File
File diff suppressed because it is too large Load Diff
+346
View File
@@ -0,0 +1,346 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Common prototypes */
#include "prot_fx.h" /* Common prototypes */
#include "cnst_fx.h"
#include "stl.h"
/*-------------------------------------------------------------------*
* Rescale_exc:
*
* Find absolute maximum of excitation
* Fin scaling factor to apply the excitation and its related memory
* Scale excitation and total excitation (exc2)
*-------------------------------------------------------------------*/
Word16 Rescale_exc(
Word16 dct_post_old_exc_fx[], /* i/o: Music post processing memory */
Word16 exc[], /* i/o: excitation to rescale Q_exc */
Word16 bwe_exc[],
Word16 *last_exc_dct_in,
Word16 lg, /* i : frame size */
Word16 lg32,
Word32 L_gain_code, /* i : decoded codebook gain Q16 */
Word16 *sQ_exc, /* i/o: Excitation scaling factor */
Word16 *sQsubfr, /* i/o: Past excitation scaling factors */
Word16 exc2[], /* o : local excitation vector */
Word16 i_subfr, /* i : subframe number */
const Word16 coder_type
)
{
Word16 i, tmp, max, new_Q;
/*-------------------------------------------
* find maximum of absolute excitation
*-------------------------------------------*/
max = s_max(abs_s(exc[0]), 1);
FOR (i = 1; i < lg; i++)
{
tmp = abs_s(exc[i]);
max = s_max(max, tmp);
}
/*----------------------------------------------
* find scaling (tmp) to set max = [2048..4096[
*----------------------------------------------*/
tmp = sub(add(norm_s(max), *sQ_exc), 3);
tmp = s_min(tmp, 12);
/*----------------------------------------------
* find scaling (new_Q) to keep gain_code < 2048
*----------------------------------------------*/
new_Q = add(tmp, 1);
tmp = sub(norm_l(L_or(L_gain_code, 1)), 3); /* to get to 0x08000000L (L_or with 1 to avoid norm_l(0)) */
tmp = s_min(tmp, new_Q);
tmp = s_max(tmp, 0);
tmp = sub(tmp, 1);
/*#define REMOVE_EXCITATION_PER_FRAME_SCALING */
/*----------------------------------------------
* new_Q = smallest Q since 4 subframes (20ms)
*----------------------------------------------*/
IF( sub( coder_type, TRANSITION ) == 0 )
{
tmp = s_min(tmp, 7);
}
ELSE IF (sub(coder_type,INACTIVE)==0)
{
tmp = s_min(tmp, 13);
}
ELSE IF( sub(lg,L_SUBFR) > 0 )/* --> can only happen in AUDIO mode */
{
tmp = s_min(tmp, 4); /* Limitation of the scaling gain because the frequency domain will add much more energy to the excitation*/
if( L_sub(L_abs(L_gain_code), 3276800) >= 0 ) /*(1-gain_pit)*past gain code*4 > 50 */
{
tmp = s_min(tmp, 2); /* Limitation of the scaling gain because the frequency domain might add much more energy to the excitation*/
}
}
new_Q = s_min(tmp, sQsubfr[0]);
IF(sub(lg, L_SUBFR)==0)
{
FOR(i = L_Q_MEM-1; i >= 1; i--)
{
new_Q = s_min(new_Q, sQsubfr[i]);
sQsubfr[i] = sQsubfr[i-1];
move16();
}
}
ELSE
{
IF(sub(lg, 2*L_SUBFR)==0)
{
new_Q = s_min(new_Q, sQsubfr[L_Q_MEM-1]);
FOR(i = L_Q_MEM-1; i >= 2; i--)
{
sQsubfr[i] = sQsubfr[1];
move16();
}
sQsubfr[1] = tmp;
move16();
sQsubfr[0] = tmp;
move16();
}
ELSE
{
set16_fx(sQsubfr, tmp, L_Q_MEM);
}
}
sQsubfr[0] = tmp;
move16();
/*----------------------------------------------
* rescale excitation and associated memories
*----------------------------------------------*/
tmp = sub(new_Q, *sQ_exc);
IF (tmp != 0)
{
Scale_sig(exc-L_EXC_MEM_DEC, add(L_EXC_MEM_DEC, lg), tmp);
IF(last_exc_dct_in != NULL)
{
Scale_sig(last_exc_dct_in, L_FRAME, tmp);
}
IF(bwe_exc != NULL)
{
Scale_sig(bwe_exc-PIT16k_MAX*2, add(PIT16k_MAX*2, lg32), tmp);
}
IF(exc2 != NULL)
{
Scale_sig(exc2, i_subfr, tmp);
}
IF(dct_post_old_exc_fx != NULL)
{
Scale_sig(dct_post_old_exc_fx, DCT_L_POST-OFFSET2, tmp);
}
}
/* scaling factor of excitation (-1..12) */
*sQ_exc = new_Q;
move16();
return tmp;
}
/*-------------------------------------------------------------------*
* Rescale_mem:
*
* this function should be called after excitation update (4 subfr) and before frame synthesis
* Rescale excitation related memories
*-------------------------------------------------------------------*/
void Rescale_mem(
const Word16 Q_exc, /* i : current excitation scaling (>=0) */
Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */
Word16 *Q_syn, /* i/o : scaling factor of frame */
Word16 *mem_syn2, /* i/o : modified synthesis memory */
Word16 *mem_syn_clas_estim_fx, /* i/o : old 12k8 core memory for classification */
const Word16 MaxScaling, /* i: Minimal difference between excitation scaling and synthesis scaling */
Word16 *mem_deemph, /* i/o: speech deemph filter memory */
Word16 *pst_old_syn, /* i/o: psfiler */
Word16 *pst_mem_deemp_err, /* i/o: psfiler */
Word16 *mem_agc,
PFSTAT *pf_stat, /* i/o: All memories related to NB post filter */
const Word16 Vad_flag,
const Word16 Cna_flag,
const Word16 *tmp_buffer /* tmp_buffer in Q-1 */
)
{
Word16 exp_scale, new_Q, tmp, i;
/*-------------------------------------------------------------------*
* find scaling of synthesis (based on min of current frame and last frame)
* scaling factor of synthesis (-1..6)
*-------------------------------------------------------------------*/
new_Q = sub(Q_exc, MaxScaling);
tmp = 1;
move16();
IF(tmp_buffer != NULL)
{
/* use the temporary synthesis in Q-1 to estimate the scaling */
FOR (i = 0; i < L_FRAME; i++)
{
tmp = s_max(abs_s(tmp_buffer[i]), tmp);
}
/* we add Q_syn which represents the actual scaling of the memories prev_Q_syn represents the last potential scaling */
tmp = sub(add(norm_s(tmp), -1), 3); /* -2 ... 12 */
}
ELSE
{
FOR (i = 0; i < M; i++)
{
tmp = s_max(abs_s(mem_syn2[i]), tmp);
tmp = s_max(abs_s(pst_old_syn[i]), tmp);
tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp);
}
FOR (; i < L_SUBFR; i++)
{
tmp = s_max(abs_s(pst_old_syn[i]), tmp);
tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp);
}
FOR (; i < L_SYN_MEM_CLAS_ESTIM; i++)
{
tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp);
tmp = s_max(abs_s(pst_old_syn[i]), tmp);
}
FOR (; i < NBPSF_PIT_MAX; i++)
{
tmp = s_max(abs_s(pst_old_syn[i]), tmp);
}
/* we add Q_syn which represents the actual scaling of the memories prev_Q_syn represents the last potential scaling */
tmp = sub(add(norm_s(tmp), *Q_syn), 2); /* -2 ... 12 */
}
IF(Vad_flag != 0)
{
new_Q = s_min(sub(Q_exc,2), tmp);
}
ELSE IF(Cna_flag != 0)
{
new_Q = s_min(Q_exc, sub(tmp, 2));
}
ELSE
{
new_Q = s_min(Q_exc, tmp);
}
new_Q = s_min(new_Q, 12); /* */
new_Q = s_max(new_Q, -1); /* */
/*#define REMOVE_SYNTHESIS_PER_FRAME_SCALING */
tmp = s_min(new_Q, *prev_Q_syn);
*prev_Q_syn = new_Q;
move16();
exp_scale = sub(tmp, *Q_syn);
*Q_syn = tmp;
move16();
/* rescale synthesis memory (mem_syn2) */
Scale_sig(mem_syn2, M, exp_scale);
Scale_sig(mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM, exp_scale);
/*Scale_sig(core_old_syn, L_SYN_MEM, exp_scale);*/
Scale_sig(mem_deemph, 1, exp_scale);
Scale_sig(pst_old_syn, NBPSF_PIT_MAX, exp_scale);
Scale_sig(pst_mem_deemp_err, 1, exp_scale);
Scale_sig(pf_stat->mem_pf_in, L_SUBFR, exp_scale); /* NB post_filter mem */
Scale_sig(pf_stat->mem_res2, DECMEM_RES2, exp_scale); /* NB post_filter mem */
Scale_sig(pf_stat->mem_stp, L_SUBFR, exp_scale); /* NB post_filter mem */
Scale_sig(mem_agc, 1, exp_scale); /* NB post_filter mem */
return;
}
/*-------------------------------------------------------------------*
* Scale_sig32
* Note: In order to save complexity, call function only, if exp0 != 0
* Up/down scale a 32 bits vector
*-------------------------------------------------------------------*/
void scale_sig32(
Word32 x[], /* i/o: signal to scale Qx */
const Word16 lg, /* i : size of x[] Q0 */
const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */
)
{
Word16 i;
FOR (i = 0; i < lg; i++)
{
/* saturation can occur here */
x[i] = L_shl(x[i], exp0);
move32();
}
}
/*-------------------------------------------------------------------*
* Rescale_mem:
*
* this function should be called after excitation update (4 subfr) and before frame synthesis
* Rescale excitation related memories
*-------------------------------------------------------------------*/
Word16 rescale_mem(
const Word16 *Q_exc, /* i : current excitation scaling (>=0) */
Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */
Word16 *Q_syn, /* i/o : scaling factor of frame */
Word16 *mem_syn2, /* i/o : modified synthesis memory */
Word16 *syn, /* i/o : synthesis to rescale Q_syn */
Word16 mem_len, /* i : lenght of modified synthesis memory */
Word16 i_subfr /* i : subframe number */
)
{
Word16 exp_scale, new_Q, tmp;
Word16 i, max16, max_scale;
max16 = 0;
move16();
FOR (i = 0; i < mem_len; i++ )
{
max16 = s_max(max16, abs_s(mem_syn2[i]));
}
IF( syn != NULL )
{
FOR (i = 0; i < i_subfr; i++ )
{
max16 = s_max(max16, abs_s(syn[i]));
}
}
max_scale = 15;
move16();
IF(max16 > 0)
{
max_scale = add(norm_s(max16), -3);
}
/*-------------------------------------------------------------------*
* find scaling of synthesis (based on min of current frame and last frame)
* scaling factor of synthesis (-1..6)
*-------------------------------------------------------------------*/
new_Q = sub(*Q_exc, 3);
new_Q = s_max(new_Q, -1);
tmp = add(max_scale, *Q_syn);
if( sub(s_min(new_Q, *prev_Q_syn), tmp) > 0)
{
new_Q = s_max(tmp, -1);
}
tmp = s_min(new_Q, *prev_Q_syn);
*prev_Q_syn = new_Q;
move16();
exp_scale = sub(tmp, *Q_syn);
*Q_syn = tmp;
move16();
/* rescale synthesis memory (mem_syn2) */
Scale_sig(mem_syn2, mem_len, exp_scale);
IF(syn != NULL)
{
Scale_sig(syn, i_subfr, exp_scale);
}
return exp_scale;
}
+245
View File
@@ -0,0 +1,245 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Common constants */
#include "prot_fx.h" /* Function prototypes */
#include "stl.h" /* required for wmc_tool */
#include "basop_mpy.h"
/*-------------------------------------------------------------------*
* Local constants
*-------------------------------------------------------------------*/
#define BIN_4000 80 /* The frequency bin corresponding to 4kHz */
#define MAX_BANDEXC 20
#define NB_TH3_MIN 30
#define NB_TH1_MIN 30
#define TH_0_MAX_FX 9600 /* Q11 -> 1.5*3.125 */
#define TH_1_MAX_FX 8640 /* Q11 -> 1.5*2.8125 */
#define TH_2_MAX_FX 6720 /* Q11 -> 1.5*2.1875 */
#define TH_3_MAX_FX 5760 /* Q11 -> 1.5*1.875 */
#define TH_UP_FX 320 /* Q11 -> 0.15625 */
#define TH_DW_FX 320 /* Q11 -> 0.15625 */
/*------------------------------------------------------------------------*
* stab_est()
*
* Signal stability estimation based on energy variation
*------------------------------------------------------------------------*/
Word16 stab_est_fx(
Word16 etot, /* i : Total energy of the current frame */
Word16 *lt_diff_etot, /* i/o : Long term total energy variation */
Word16 *mem_etot, /* i/o : Total energy memory */
Word16 *nb_thr_3, /* i/o : Number of consecutives frames of level 3 */
Word16 *nb_thr_1, /* i/o : Number of consecutives frames of level 1 */
Word16 *thresh, /* i/o : Detection thresold */
Word16 *last_music_flag,/* i/o : Previous music detection ouptut */
Word16 vad_flag
)
{
Word16 i, music_flag2, tmp16, exp1, exp2;
Word16 mean_diff;
Word16 dev;
Word32 L_tmp;
/*------------------------------------------------------------------------*
* Find mean of the past MAX_LT frames energy variation
*------------------------------------------------------------------------*/
L_tmp = L_deposit_l(0);
FOR (i = 1; i<MAX_LT; i++)
{
/*mean_diff += lt_diff_etot[i-1] * INV_MAX_LT; divide by MAX_LT */
L_tmp = L_mac(L_tmp, lt_diff_etot[i-1], INV_MAX_LT_FX);
lt_diff_etot[i-1] = lt_diff_etot[i];
move16();
}
/*mean_diff += lt_diff_etot[i-1] * INV_MAX_LT; */ /* divide by MAX_LT */
L_tmp = L_mac(L_tmp, lt_diff_etot[i-1], INV_MAX_LT_FX);
mean_diff = round_fx(L_tmp); /*Q8 */
/*------------------------------------------------------------------------*
* Find statistical deviation of the energy variation history
* against the last 15 frames
*------------------------------------------------------------------------*/
tmp16 = sub(lt_diff_etot[MAX_LT-15], mean_diff);
L_tmp = L_mult0(tmp16, tmp16);
FOR(i = MAX_LT-15+1; i<MAX_LT; i++)
{
/*fcorr += ftmp_c*ftmp_c;*/
tmp16 = sub(lt_diff_etot[i], mean_diff);
L_tmp = L_mac0(L_tmp, tmp16, tmp16);
}
/*------------------------------------------------------------------------*
* Update
*------------------------------------------------------------------------*/
lt_diff_etot[i-1] = sub(etot, *mem_etot);
move16();
*mem_etot = etot;
move16();
/*------------------------------------------------------------------------*
* Compute statistical deviation
*------------------------------------------------------------------------*/
/* dev = (float)0.7745967f*sqrt(fcorr / 15); */
L_tmp = Mpy_32_16_1(L_tmp, 1311); /*-> 1/25 (1/(MAX_LT-15))*/
exp1 = norm_l(L_tmp);
L_tmp = L_shl(L_tmp, exp1);
tmp16 = round_fx(L_tmp);
exp2 = sub(31, exp1);
L_tmp = Isqrt_lc(L_tmp, &exp2);
L_tmp = Mpy_32_16_1(L_tmp, tmp16); /* we now have sqrt(L_corr) Q24 (8+16)*/
exp2 = sub(31-15, sub(exp1, exp2)); /* for Q8 (because of -8^2 from Etot)*/
L_tmp = L_shl(L_tmp, exp2); /* Q8 + Q16*/
dev = extract_h(L_shl(L_tmp, 3)); /* Q(24+3-16) -> Q11 */
/*------------------------------------------------------------------------*
* State machine to decide level of inter-harmonic noise reduction and
* (only if this frame is GOOD or if we are already far from NB_BFI_THR)
* (if music_flag2 is 0, the spectral modification is deactivated, otherwise, it is activated)
*------------------------------------------------------------------------*/
music_flag2 = 0;
move16();/* deactivate spectral modification (if music_flag2 != 0 is activated) */
test();
/*--------------------------------------------------------------------*
* statistical deviation < thresh3 and last signal category type >= 3
* (last category was "tonal" and the new one is "very tonal")
*--------------------------------------------------------------------*/
test();
test();
test();
IF ((sub(dev, thresh[3])< 0 ) && (sub(*last_music_flag,3) >= 0) )
{
music_flag2 = 4;
move16();
*nb_thr_3 += 1;
move16();
*nb_thr_1 = 0;
move16();
}
/*--------------------------------------------------------------------*
* statistical deviation < thresh2 and last signal category type >= 2
* (last category was "moderatly tonal" and the new one is a "tonal" )
*--------------------------------------------------------------------*/
ELSE IF ((sub(dev, thresh[2])< 0 ) && (sub(*last_music_flag,2) >= 0) )
{
music_flag2 = 3;
move16();
*nb_thr_3 += 1;
move16();
*nb_thr_1 = 0;
move16();
}
/*--------------------------------------------------------------------*
* statistical deviation < thresh1 and last signal category type >= 1
* (last category was "slightly tonal" and the new one is a "moderatly tonal")
*--------------------------------------------------------------------*/
ELSE IF ((sub(dev, thresh[1])< 0 ) && (sub(*last_music_flag,1) >= 0) )
{
music_flag2 = 2;
move16();
}
/*--------------------------------------------------------------------*
* statistical deviation < thresh0
* (last category was "not tonal" and the new one is "slightly tonal")
*--------------------------------------------------------------------*/
ELSE IF ((sub(dev, thresh[0]) < 0 ) )
{
music_flag2 = 1;
move16();/* [2000, 4000] Hz */
}
/*--------------------------------------------------------------------*
* statistical deviation > thresh0
* (Statistical deviation is high: the new tonal category is not tonal)
*--------------------------------------------------------------------*/
ELSE
{
*nb_thr_1 = add(*nb_thr_1,1);
*nb_thr_3 = 0;
move16();
}
/*------------------------------------------------------------------------*
* Update the thresholds
*------------------------------------------------------------------------*/
IF (sub(*nb_thr_3,NB_TH3_MIN) > 0)
{
/* the number of consecutive categories type 3 or 4 (most tonal and tonal) */
/* is greater than 30 frames ->increase the deviations thresholds to allow more variation */
thresh[0] = add(thresh[0], TH_UP_FX);
move16(); /*Q11 */
thresh[1] = add(thresh[1], TH_UP_FX);
move16();
thresh[2] = add(thresh[2], TH_UP_FX);
move16();
thresh[3] = add(thresh[3], TH_UP_FX);
move16();
}
ELSE IF (sub(*nb_thr_1,NB_TH1_MIN) > 0)
{
/* the number of consecutive categories type 0 (non tonal frames) */
/* is greater than 30 frames -> decrease the deviations thresholds to allow less variation */
thresh[0] = sub(thresh[0], TH_DW_FX);
move16(); /*Q11 */
thresh[1] = sub(thresh[1], TH_DW_FX);
move16();
thresh[2] = sub(thresh[2], TH_DW_FX);
move16();
thresh[3] = sub(thresh[3], TH_DW_FX);
move16();
}
/* limitation of the threshold (this local macro stores the highest of the two and it also
counts the # of operations) */
move16();
move16();
move16();
thresh[0] = s_max(thresh[0], TH_0_MIN2_FX);
thresh[1] = s_max(thresh[1], TH_1_MIN2_FX);
thresh[2] = s_max(thresh[2], TH_2_MIN2_FX);
move16();
move16();
move16();
thresh[0] = s_min(thresh[0], TH_0_MAX_FX);
thresh[1] = s_min(thresh[1], TH_1_MAX_FX);
thresh[2] = s_min(thresh[2], TH_2_MAX_FX);
move16();
move16();
thresh[3] = s_max(thresh[3], TH_3_MIN2_FX);
thresh[3] = s_min(thresh[3], TH_3_MAX_FX);
/*------------------------------------------------------------------------*
* Final update
*------------------------------------------------------------------------*/
*last_music_flag = music_flag2;
move16();
if (vad_flag == 0)
{
music_flag2 = 0;
move16();
}
return music_flag2;
}
+676
View File
@@ -0,0 +1,676 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#ifndef STAT_COM_H
#define STAT_COM_H
#include "options.h"
#include "basop_util.h"
#include "cnst_fx.h"
/*----------------------------------------------------------------------------------*
* Declaration of structures
*----------------------------------------------------------------------------------*/
/* Forward declaration of Decoder_State_fx */
struct Decoder_State_fx;
/*-----------------------------------------------------------*
* EV-VBR NB postfilter static variables
*-----------------------------------------------------------*/
typedef struct
{
Word16 on; /* On/off flag */
Word16 reset; /* reset flag */
Word16 mem_pf_in[L_SUBFR]; /* Input memory */
Word16 mem_stp[L_SUBFR]; /* 1/A(gamma1) memory */
Word16 mem_res2[DECMEM_RES2]; /* A(gamma2) residual */
Word16 mem_zero[M]; /* null memory to compute i.r. of A(gamma2)/A(gamma1) */
Word16 gain_prec; /* for gain adjustment */
} PFSTAT;
typedef struct
{
Word16 a_fx[MAXLAG_WI];
Word16 b_fx[MAXLAG_WI];
Word16 lag_fx;
Word16 nH_fx;
Word16 nH_4kHz_fx;
Word16 upper_cut_off_freq_of_interest_fx;
Word16 upper_cut_off_freq_fx;
Word16 Fs_fx;
Word16 Q;
} DTFS_STRUCTURE_FX;
typedef struct
{
Word16 lead_sign_ind;
UWord32 index, size;
Word16 dim, k_val;
} PvqEntry_fx;
typedef struct
{
UWord8 buf[MAX_SIZEBUF_PBITSTREAM];
Word16 curPos;
Word32 numByte;
Word32 numbits;
Word32 maxBytes;
} BITSTREAM_FX, *PBITSTREAM_FX;
typedef struct
{
PBITSTREAM_FX bsInst;
Word32 low;
Word32 high;
Word32 value;
Word16 bits_to_follow;
Word32 num_bits;
Word32 max_bits;
} ARCODEC_FX, *PARCODEC_FX;
/*---------------------------------------------------------------*
* Encoder/Decoder Static RAM *
*---------------------------------------------------------------*/
typedef struct
{
/*Coding mode info*/
Word16 mode_index;
/*LPC info*/
Word8 midLpc; /*Flag for using or not mid LPC for the current frame*/
Word8 midLpc_enable; /*Flag enabling or not the mid LPC for the current mode_index*/
/*ICB flags*/
Word8 pre_emphasis;
Word8 pitch_sharpening; /*Flag for triggering pitch sharpening*/
Word8 phase_scrambling; /*Flag for triggering phase scrambling*/
Word16 formant_enh; /*Flag for triggering formant enhancement: Q15 representing 0...1.0f */
Word8 formant_tilt;
Word8 voice_tilt; /*Flag for triggering new voice factor tilt*/
Word16 formant_enh_num;
Word16 formant_enh_den;
Word16 bpf_mode;
Word16 nrg_mode;
Word16 nrg_bits;
Word16 ltp_mode;
Word16 ltp_bits;
Word16 ltf_mode;
Word16 ltf_bits;
Word16 gains_mode[NB_SUBFR16k];
Word16 fixed_cdk_index[NB_SUBFR16k];
} ACELP_config;
/*tns_base.h*/
/** TNS configuration.
* Use InitTnsConfiguration to initialize it.
*/
typedef struct
{
Word16 maxOrder;
/** Maximum number of filters. */
Word16 nMaxFilters;
/** Parameters for each TNS filter */
struct TnsParameters const * pTnsParameters;
/** Lower borders for each filter.
* Upper border for the first filter is nsbBorders-1.
* Upper borders for other filters is the lower border of previous filter.
*/
Word16 iFilterBorders[TNS_MAX_NUM_OF_FILTERS+1];
} STnsConfig;
/** TNS filter.
* Parameters that define a TNS filter.
*/
typedef struct
{
/** Number of subbands covered by the filter. */
Word16 spectrumLength;
/** Filter order. */
Word16 order;
/** Quantized filter coefficients. */
Word16 coefIndex[TNS_MAX_FILTER_ORDER];
/** Prediction gain. The ratio of a signal and TNS residual energy. */
Word16 predictionGain; /* exponent = PRED_GAIN_E */
/** Average squared filter coefficient. */
Word16 avgSqrCoef; /* exponent = 0 */
} STnsFilter;
/** TNS data.
* TNS data describing all active filters.
*/
typedef struct
{
/** Number of active filters. */
Word16 nFilters;
/** Active filters. */
STnsFilter filter[TNS_MAX_NUM_OF_FILTERS];
} STnsData;
typedef enum
{
TNS_NO_ERROR = 0,
TNS_FATAL_ERROR
} TNS_ERROR;
typedef struct
{
/* TCX mdct window */
const PWord16 *tcx_mdct_window;
const PWord16 *tcx_mdct_window_half;
const PWord16 *tcx_mdct_window_minimum;
const PWord16 *tcx_mdct_window_trans;
Word16 tcx_aldo_window_1[L_FRAME32k*9/32];
PWord16 tcx_aldo_window_1_trunc[L_FRAME32k*7/32];
PWord16 tcx_aldo_window_2[L_FRAME32k*7/32];
Word16 last_aldo;
Word16 tcx5Size; /* Size of the TCX5 spectrum. Always 5ms. */
Word16 tcx_mdct_window_length;
Word16 tcx_mdct_window_half_length; /*length of the "half" overlap window*/
Word16 tcx_mdct_window_min_length; /* length of the "minimum" overlap */
Word16 tcx_mdct_window_trans_length; /* length of the ACELP->TCX overlap */
Word16 tcx_mdct_window_delay; /*length of window delay*/
Word16 tcx_offset;
Word16 tcx_mdct_window_length_old; /*for keeping old value for sample rate switching */
/* TCX mdct window */
const PWord16 *tcx_mdct_windowFB;
const PWord16 *tcx_mdct_window_halfFB;
const PWord16 *tcx_mdct_window_minimumFB;
const PWord16 *tcx_mdct_window_transFB;
Word16 tcx_aldo_window_1_FB[L_FRAME_MAX*9/32];
PWord16 tcx_aldo_window_1_FB_trunc[L_FRAME_MAX*7/32];
PWord16 tcx_aldo_window_2_FB[L_FRAME_MAX*7/32];
Word16 tcx5SizeFB; /* Size of the TCX5 spectrum. Always 5ms. */
Word16 tcx_mdct_window_lengthFB;
Word16 tcx_mdct_window_half_lengthFB; /*length of the "half" overlap window*/
Word16 tcx_mdct_window_min_lengthFB; /* length of the "minimum" overlap */
Word16 tcx_mdct_window_trans_lengthFB; /* length of the ACELP->TCX overlap */
Word16 tcx_mdct_window_delayFB; /*length of window delay*/
Word16 tcx_offsetFB;
Word16 tcx_coded_lines; /* max number of coded lines, depending on bandwidth mode */
Word16 tcx_curr_overlap_mode; /* window overlap of current frame (0: full, 2: none, or 3: half) */
Word16 tcx_last_overlap_mode; /* previous window overlap, i.e. left-side overlap of current frame */
/* FAC window */
Word16 lfacNext;
Word16 lfacNextFB;
/* TNS */
Word8 fIsTNSAllowed;
STnsConfig tnsConfig[2][2];
STnsConfig const * pCurrentTnsConfig;
/*Quantization*/
Word16 sq_rounding; /*set the sq deadzone (no deadzone=0.5f)*/
Word8 tcxRateLoopOpt;
/*Bandwidth*/
Word16 preemph_fac; /*preemphasis factor*/
Word16 bandwidth;
/* Context HM - Residual Quantization*/
Word8 ctx_hm; /*Flag for enabling Context HM*/
Word8 resq; /*Flag for enabling Residual Quantization*/
Word16 coder_type; /*INACTIVE, UNVOICED,VOICED,GENERIC*/
Word16 na_scale;
Word32 SFM2;
} TCX_config;
/* prot.h */
typedef struct
{
Word16 bits; /* bits per subframe */
Word16 nbiter; /* number of iterations */
Word16 alp; /* initial energy of all fixed pulses, exponent = ALP_E */
Word8 nb_pulse; /* number of pulses */
Word8 fixedpulses; /* number of pulses whose position is determined from correlation and not by iteration */
Word8 nbpos[13]; /* number of positions tried in the pair-wise search */
Word8 codetrackpos; /* ordering of tracks -mode */
} PulseConfig;
/* fd_cng_common.h */
/* CLDFB-based CNG setup */
typedef struct
{
Word16 fftlen; /* FFT length */
Word16 stopFFTbin; /* Number of FFT bins to be actually processed */
Word16 numPartitions; /* Number of partitions */
const Word16* sidPartitions; /* Upper boundaries for grouping the (sub)bands into partitions when transmitting SID frames (define as NULL pointer to avoid grouping) */
Word16 numShapingPartitions; /* Number of partitions */
const Word16* shapingPartitions; /* Upper boundaries for grouping the (sub)bands into partitions for shaping at the decoder (define as NULL pointer to avoid grouping) */
} FD_CNG_SETUP;
/* Scale setup */
typedef struct
{
Word32 bitrateFrom;
Word32 bitrateTo;
Word16 scale;
Word8 bwmode;
} SCALE_SETUP;
/* Arrays and variables common to encoder and decoder */
typedef struct
{
FD_CNG_SETUP FdCngSetup;
Word16 numSlots; /* Number of time slots in CLDFB matrix */
Word16 regularStopBand;/* Number of CLDFB bands to be considered */
Word16 numCoreBands; /* Number of core bands to be decomposed into FFT subbands */
Word16 stopBand; /* Total number of (sub)bands to be considered */
Word16 startBand; /* First (sub)band to be considered */
Word16 stopFFTbin; /* Total number of FFT subbands */
Word16 frameSize; /* Frame size in samples */
Word16 fftlen; /* FFT length used for the decomposition */
Word16 fftlenShift;
Word16 fftlenFac;
Word16 timeDomainBuffer[L_FRAME16k];
Word32 fftBuffer[FFTLEN];
Word16 *olapBufferAna; /* points to FD_CNG_DEC->olapBufferAna[320] in case of decoder */
Word16 olapBufferSynth[FFTLEN];
Word16 *olapBufferSynth2; /* points to FD_CNG_DEC->olapBufferSynth2[FFTLEN] in case of decoder */
const PWord16 * olapWinAna;
const PWord16 * olapWinSyn;
Word16 msM_win;
Word16 msM_subwin;
Word16 msFrCnt_init_counter; /* Frame counter at initialization */
Word16 init_old;
Word16 msFrCnt_init_thresh;
Word16 msFrCnt; /* Frame counter */
Word32 msAlphaCor[2]; /* Correction factor (smoothed) */
Word16 msSlope[2];
Word32 msQeqInvAv[2];
Word16 msQeqInvAv_exp[2];
Word16 msMinBufferPtr;
Word32 msPsdSum[2];
Word32 msPeriodogSum[2];
Word16 msPeriodogSum_exp[2];
Word16 offsetflag;
Word32 periodog[PERIODOGLEN]; /* Periodogram */
Word16 periodog_exp;
Word16 exp_cldfb_periodog;
Word32 cngNoiseLevel[FFTCLDFBLEN]; /* Noise level applied for the CNG in each (sub)band */
Word16 cngNoiseLevelExp;
Word16 seed; /* Seed memory (for random function) */
Word16 npart; /* Number of partitions */
Word16 midband[NPART]; /* Central band of each partition */
Word16 nFFTpart; /* Number of hybrid spectral partitions */
Word16 part[NPART]; /* Partition upper boundaries (band indices starting from 0) */
Word16 psize[NPART]; /* Partition sizes */
Word16 psize_norm[NPART]; /* Partition sizes, fractional variable */
Word16 psize_norm_exp; /* Partition sizes exponent for fractional variable */
Word16 psize_inv[NPART]; /* Inverse of partition sizes */
Word16 FFTscalingFactor; /* Squared ratio between core signal analysis FFT and noise estimator FFT */
Word16 scalingFactor;
Word16 invScalingFactor;
Word16 nCLDFBpart; /* Number of CLDFB spectral partitions */
Word16 CLDFBpart[NPARTCLDFB]; /* CLDFB Partition upper boundaries (band indices starting from 0 above the core coder bands) */
Word16 CLDFBpsize_inv[NPARTCLDFB];/* Inverse of CLDFB partition sizes */
Word16 inactive_frame_counter;
Word16 sid_frame_counter;
Word16 active_frame_counter;
Word32 sidNoiseEst[NPART]; /* Transmitted noise level */
Word16 sidNoiseEstExp;
Word16 frame_type_previous;
Word16 A_cng[M+1];
Word16 exc_cng[L_FRAME16k];
Word32 CngBitrate;
Word16 CngBandwidth;
Word16 flag_noisy_speech;
Word16 likelihood_noisy_speech;
}
FD_CNG_COM;
typedef FD_CNG_COM *HANDLE_FD_CNG_COM;
/*parameter_bitmaping.h*/
/** Function that gets specific value from p.
* @param p Pointer to a variable that can also be structure or array.
* @param index Index of a variable when p is an array, otherwise 0.
* @param pValue Pointer to the value.
* @return Substructure associated with this value or NULL if there is none.
*/
typedef void const * (* TGetParamValue)(void const * p, Word16 index, Word16 * pValue);
/** Function that puts specific value to p.
* @param p Pointer to a variable that can also be structure or array.
* @param index Index of a variable when p is an array, otherwise 0.
* @param value The value.
* @return Substructure associated with this value or NULL if there is none.
*/
typedef void * (* TSetParamValue)(void * p, Word16 index, Word16 value);
/** Function that return required number of bits for a value when it is coded.
* @param value The value.
* @param index Index of a variable when it is an element of an array, otherwise 0.
* @return Number of bits required to code the value.
*/
typedef Word16 (* TGetNumberOfBits)(Word16 value, Word16 index);
/** Function that encodes a value.
* @param value The value.
* @param index Index of a variable when it is an element of an array, otherwise 0.
* @return Coded value.
*/
typedef Word16 (* TEncodeValue)(Word16 value, Word16 index);
/** Function that decodes a value.
* @param st Decoder state.
* @param index Index of a variable when it is an element of an array, otherwise 0.
* @param pValue A pointer where the decoded value should be stored.
* @return Number of bits read from the bitstream.
*/
typedef Word16 (* TDecodeValue)(struct Decoder_State_fx *st, Word16 index, Word16 * pValue);
/** Structure that defines mapping between a parameter and a bistream. */
typedef struct ParamBitMap
{
/** Number of bits in a bitstream required for the parameter.
* If nBits is equal to 0 then GetNumberOfBits is used.
*/
Word16 nBits;
/** Function to get the number of bits required for a value of this parameter.
* If nBits != 0 it is not used and can be set to NULL.
* If fZeroAllowed == 0 then GetNumberOfBits must take care of this.
*/
TGetNumberOfBits GetNumberOfBits;
/** If fZeroAllowed is 0 then the value can be zero.
* If the value can't be zero then value-1 is stored in a bitstream.
* If EncodeValue is not equal to NULL, then the encode/decode function
* must take care of this flag - there is no additional processing in parameter bitmapping.
* If EncodeValue is equal to NULL, then the encode/decode function takes care of this.
*/
Word8 fZeroAllowed;
/** Function to get the value of this parameter.
* The function returns a pointer to be used in functions in pSubParamBitMap.
* If the function returns NULL then the same pointer as for the current
* parameter is to be used.
* The function should not do any additional processing if fZeroAllowed == 0,
* but just set the value as it is.
*/
TGetParamValue GetParamValue;
/** Function to set the value of this parameter.
* The function returns a pointer to be used in functions in pSubParamBitMap.
* If the function returns NULL then the same pointer as for the current
* parameter is to be used.
* The function should not do any additional processing if fZeroAllowed == 0,
* but just set the value as it is.
*/
TSetParamValue SetParamValue;
/** Function to encode a value of this parameter.
* When it is equal to NULL, fixed-width coding is used.
* If fZeroAllowed == 0 then EncodeValue must take care of this.
*/
TEncodeValue EncodeValue;
/** Function to decode a value of this parameter.
* When it is equal to NULL, fixed-width coding is used.
* If fZeroAllowed == 0 then DecodeValue must take care of this.
*/
TDecodeValue DecodeValue;
/** Pointer to the map for substructure.
* The number of structures is determined by this parameter's value.
* NULL means that there is no substructure.
*/
struct ParamsBitMap const * pSubParamBitMap;
} ParamBitMap;
/** Structure that defines mapping between parameters and a bistream. */
typedef struct ParamsBitMap
{
/** Number of parameters in params. */
Word16 nParams;
/** Definition of the mapping for each parameter. */
ParamBitMap params[NPARAMS_MAX];
} ParamsBitMap;
/*tns_tables.h*/
struct TnsParameters
{
/* Parameters for each TNS filter */
Word16 startLineFrequency; /* Starting lower frequency of the TNS filter [20..16000] */
Word16 nSubdivisions; /* Number of spectrum subdivisions in which the filter operates [1..8) */
Word16 minPredictionGain; /* Minimum prediction gain required to turn on the TNS filter. Exponent = PRED_GAIN_E */
Word16 minAvgSqrCoef; /* Minimum average square of coefficients required to turn on the TNS filter. Exponent = 0 */
};
/**********************************************/
/* Helper structures for hufmann table coding */
/**********************************************/
typedef struct
{
Word8 value;
Word16 code;
Word8 nBits;
} Coding;
/* Scale TCX setup */
typedef struct
{
Word16 bwmode;
Word32 bitrateFrom;
Word32 bitrateTo;
Word16 scale;
} SCALE_TCX_SETUP;
/* glob_con.h */
typedef struct
{
Word16 frame_bits; /*Bits per frame*/
Word16 frame_net_bits; /*Net Bits per frame*/
Word8 transmission_bits; /*max=1*/
Word8 transmission_mode[2]; /*SID,VBR/CBR*/
Word8 bandwidth_bits; /*max=2*/
Word8 bandwidth_min; /*first valid bandwidth (NB,WB,SWB,FB)*/
Word8 bandwidth_max; /*last valid bandwidth (NB,WB,SWB,FB)*/
Word8 reserved_bits; /*max=1*/
} FrameSizeParams;
typedef struct
{
Word16 lb_scale; /*!< Scale of low band area */
Word16 lb_scale16; /*!< Scale of low band area */
Word16 ov_lb_scale; /*!< Scale of adjusted overlap low band area */
Word16 hb_scale; /*!< Scale of high band area */
Word16 ov_hb_scale; /*!< Scale of adjusted overlap high band area */
} CLDFB_SCALE_FACTOR;
struct CLDFB_FILTER_BANK
{
const Word16 *p_filter; /*!< Pointer to filter coefficients */
Word16 *FilterStates; /*!< Pointer to buffer of filter states */
Word16 FilterStates_e[CLDFB_NO_COL_MAX+9]; /*!< Filter states time slot exponents */
Word16 FilterStates_eg; /*!< Filter states current exponent */
Word16 p_filter_length; /*!< Size of prototype filter. */
const Word16 *rRotVctr; /*!< Modulation tables. */
const Word16 *iRotVctr;
Word16 filterScale; /*!< filter scale */
Word16 synGain; /*!< gain for synthesis filterbank */
Word16 no_channels; /*!< Total number of channels (subbands) */
Word16 no_col; /*!< Number of time slots */
Word16 lsb; /*!< Top of low subbands */
Word16 usb; /*!< Top of high subbands */
Word16 zeros; /*!< number of zeros in filter coefficients */
Word16 anaScalefactor; /*!< Scale factor of analysis cldfb */
Word16 synScalefactor; /*!< Scale factor of synthesis cldfb */
Word16 outScalefactor; /*!< Scale factor of output data (syn only) */
Word16 synFilterHeadroom; /*!< Headroom for states in synthesis cldfb filterbank */
UWord16 flags; /*!< flags */
Word16 bandsToZero; /*!< additional bands which are zeroed in inverse modulation */
Word16 filtermode;
Word16 type;
Word16 *memory;
Word16 memory_length;
Word16 scale;
};
typedef struct CLDFB_FILTER_BANK *HANDLE_CLDFB_FILTER_BANK;
typedef struct
{
Word16 pGainTemp_m[CLDFB_NO_COL_MAX];
Word16 pGainTemp_e[CLDFB_NO_COL_MAX];
Word16 loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG];
Word16 cldfbExp;
Word16 lastCldfbExp;
} TEMPORAL_ENVELOPE_CODING_DECODER_FX;
typedef TEMPORAL_ENVELOPE_CODING_DECODER_FX* HANDLE_TEC_DEC_FX;
typedef struct
{
Word16 loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC];
Word16 loTempEnv[CLDFB_NO_COL_MAX];
Word16 loTempEnv_ns[CLDFB_NO_COL_MAX];
Word16 hiTempEnv[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV];
Word16 tranFlag;
Word16 corrFlag;
} TEMPORAL_ENVELOPE_CODING_ENCODER_FX;
typedef TEMPORAL_ENVELOPE_CODING_ENCODER_FX* HANDLE_TEC_ENC_FX;
typedef enum
{
FRAME_0 = 0,
FRAME_2 = 40,
FRAME_2_4 = 48,
FRAME_4 = 80,
FRAME_5_6 = 112,
FRAME_7_2 = 144,
FRAME_8 = 160,
FRAME_9_6 = 192,
FRAME_13_2 = 264,
FRAME_16_4 = 328,
FRAME_24_4 = 488,
FRAME_32 = 640,
FRAME_48 = 960,
FRAME_64 = 1280,
FRAME_96 = 1920,
FRAME_128 = 2560
} FRAME_SIZE;
/*---------------------------------------------------------------*
* IGF *
*---------------------------------------------------------------*/
typedef struct igf_grid_struct
{
Word16 swb_offset[IGF_MAX_SFB];
Word16 swb_offset_len;
Word16 startFrequency;
Word16 stopFrequency;
Word16 startLine;
Word16 stopLine;
Word16 startSfb; /* 15Q0, startSfb = [0, 11], IGF start sfb */
Word16 stopSfb; /* 15Q0, stopSfb = [0, 22], IGF stop sfb */
Word16 sfbWrap[IGF_MAX_TILES+1];
Word16 sbWrap[IGF_MAX_TILES];
Word16 nTiles; /* 15Q0, nTiles = [1, 4], number of tiles */
Word16 minSrcSubband;
Word16 minSrcFrequency;
Word16 tile[IGF_MAX_TILES];
Word16 infoIsRefined;
Word16 infoGranuleLen; /* 15Q0, infoGranuleLen = [0, 1200], core coder granule length */
Word16 infoTransFac; /* 1Q14 */
Word16 whiteningThreshold[2][IGF_MAX_TILES]; /* 2Q13 */
Word16 gFactor; /* 1Q14 */
Word16 fFactor; /* 1Q14 */
Word16 lFactor; /* 1Q14 */
} IGF_GRID, *H_IGF_GRID;
typedef struct IGF_INFO_struct
{
Word16 nfSeed;
Word32 sampleRate;
Word16 frameLength;
Word16 maxHopsize;
IGF_GRID grid[IGF_NOF_GRIDS];
Word16 bitRateIndex;
} IGF_INFO, *H_IGF_INFO;
typedef struct
{
Word16 *indexBuffer;
Word16 *peakIndices, *holeIndices;
Word16 numPeakIndices, numHoleIndices;
} CONTEXT_HM_CONFIG;
/* Returns: index of next coefficient */
typedef Word16 (*get_next_coeff_function)(
Word16 ii[2], /* i/o: coefficient indexes */
Word16 *pp, /* o : peak(1)/hole(0) indicator */
Word16 *idx, /* o : index in unmapped domain */
CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */
);
/*CLDFB-VAD*/
#endif
+420
View File
@@ -0,0 +1,420 @@
/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Function prototypes */
#include "stl.h"
/*---------------------------------------------------------------------*
* Local constants
*---------------------------------------------------------------------*/
#define TILT_COMP_LIM_FX 24576 /* 0.75 in Q15 */
#define GE_SHIFT 6
#define P1 (32768-ISP_SMOOTHING_QUANT_A1_FX-1)
#define P9 (32767-P1)
/*---------------------------------------------------------*
* Local functions
*---------------------------------------------------------*/
static Word16 calc_tilt_fx(const Word16 *x, const Word16 Q_shift, const Word16 len);
Word32 L_Sqrt_Q0(const Word32 x);
/*--------------------------------------------------------------------*
* stat_noise_uv_mod()
*
* Modifies excitation signal in stationary noise segments
*--------------------------------------------------------------------*/
void stat_noise_uv_mod_fx(
const Word16 coder_type, /* i : Coder type */
Word16 noisiness, /* i : noisiness parameter */
const Word16 *lsp_old, /* i : old LSP vector at 4th sfr */
const Word16 *lsp_new, /* i : LSP vector at 4th sfr */
const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr */
Word16 *Aq, /* o : A(z) quantized for the 4 subframes */
Word16 *exc2, /* i/o: excitation buffer */
Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */
const Word16 bfi , /* i : Bad frame indicator */
Word32 *ge_sm, /* i/o: smoothed excitation gain */
Word16 *uv_count, /* i/o: unvoiced counter */
Word16 *act_count, /* i/o: activation counter */
Word16 lspold_s[], /* i/o: old LSP */
Word16 *noimix_seed, /* i/o: mixture seed */
Word16 *st_min_alpha, /* i/o: minimum alpha */
Word16 *exc_pe, /* i/o: scale Q_stat_noise */
const Word32 bitrate, /* i : core bitrate */
const Word16 bwidth_fx, /* i : input bandwidth */
Word16 *Q_stat_noise, /* i/o: noise scaling */
Word16 *Q_stat_noise_ge /* i/o: noise scaling */
)
{
Word16 exctilt; /* Q15 */
Word32 vare; /* Q31 */
Word16 randval; /* Q?? */
Word16 alpha; /* Q15 */
Word16 alpha_m1; /* (1-alpha) Q15 */
Word16 min_alpha; /* Q15 */
Word16 lspnew_s[M]; /* Same for all LSP (Q15) */
Word16 oldlsp_mix[M];
Word16 midlsp_mix[M];
Word16 newlsp_mix[M];
Word16 beta; /* Q15 */
Word16 Noimix_fract; /* (noimix_fac - 1.0) in Q15 */
/* noimix_fax * x <-> x + Noimix_fract * x */
Word16 i_subfr;
Word16 i, k;
/* Work variables for div and sqrt */
Word16 tmp_nom,tmp_den,tmp_shift,tmp_res;
Word16 Qdiff,Q_local; /* new Q to be used for states Exc_pe and Ge_sm, and Exc2_local */
Word32 L_tmp_res,L_tmp, L_tmp3,L_Ge;
Word16 En_shift,Tmp;
Word16 Exc2_local[L_FRAME]; /* local_copy in scaled Q_local*/
/*---------------------------------------------------------*
* Init local variables
*---------------------------------------------------------*/
alpha = 32767;
move16();
min_alpha = 16384;
move16();
test();
test();
test();
IF (sub(coder_type,INACTIVE) == 0 && ( L_sub(bitrate,ACELP_9k60) == 0 || (L_sub(bitrate,ACELP_9k60) < 0 && sub(bwidth_fx,NB) > 0) ) )
{
min_alpha = *st_min_alpha;
move16();
/*---------------------------------------------------------*
* decode noisiness parameter
*---------------------------------------------------------*/
IF (bfi == 0)
{
tmp_den = 31;
move16();
tmp_shift = norm_s(tmp_den);
move16();
L_tmp_res = L_deposit_h(noisiness);
L_tmp_res = L_shl(L_tmp_res,sub(tmp_shift,1));
tmp_den = shl(tmp_den,tmp_shift);
move16();
tmp_res = div_l(L_tmp_res,tmp_den);
move16();
min_alpha = add(tmp_res, 16384);
move16();
/**st_min_alpha = sub(*st_min_alpha, 1638); move16();*/
min_alpha = s_max(min_alpha, sub(*st_min_alpha, 1638));
*st_min_alpha = min_alpha;
move16();
}
}
/*---------------------------------------------------------*
* Mix excitation signal with random noise
*---------------------------------------------------------*/
test();
test();
test();
IF ( sub(coder_type,INACTIVE) == 0 && ( L_sub(bitrate,ACELP_9k60) == 0 || (L_sub(bitrate,ACELP_9k60) < 0 && sub(bwidth_fx,NB) > 0) ) )
{
/* use a local working copy for scaling and filtering, not needed if input Q-range is fixed */
Copy(exc2, Exc2_local, L_FRAME);
/* bound Q for internal use, optimization possible */
Q_local = s_min(11, s_max(-1, Q_exc));
/* local excitation Q and incoming excitation Q*/
Qdiff = sub(Q_local, Q_exc);
/* only shift if incoming Q is outside [11..-1] shift is done in energy calculations aswell */
Scale_sig(Exc2_local, L_FRAME, Qdiff);
/* current excitation Q and previous stat_noise states Q */
Qdiff = sub(Q_local, *Q_stat_noise);
*Q_stat_noise_ge = GE_SHIFT;
move16(); /* assign the fixed Q for Ge_sm */
IF (Qdiff != 0)
{
Scale_sig(exc_pe, 1, Qdiff);
}
En_shift = 0;
move16();
if (sub(Q_local, 3) > 0)
{
/* increase margin for energy accumulation in calc_tilt and vare accumulation */
En_shift = sub(Q_local, 3);
}
IF (sub(min_alpha, TILT_COMP_LIM_FX) < 0)
{
FOR (i_subfr=0; i_subfr<L_FRAME; i_subfr+=L_SUBFR)
{
exctilt = calc_tilt_fx(&Exc2_local[i_subfr], En_shift, L_SUBFR); /*Q15 */
exctilt = mult(shl(sub(TILT_COMP_LIM_FX, min_alpha), 2), exctilt); /*Q15 */
preemph_fx(&Exc2_local[i_subfr],exctilt,L_SUBFR,exc_pe);
}
}
(*uv_count)++;
IF (sub(*uv_count,START_NG) <= 0)
{
alpha = 32767;
move16();
*act_count = 3;
move16();
Copy(lsp_new, lspold_s, M);
}
ELSE
{
*uv_count = s_min(*uv_count , FULL_NG);
tmp_nom = sub(*uv_count,START_NG);
tmp_den = sub(FULL_NG,START_NG);
tmp_shift = norm_s(tmp_den);
tmp_den = shl(tmp_den,tmp_shift);
tmp_res = div_s(tmp_nom,tmp_den);
tmp_res = shl(tmp_res,tmp_shift);
alpha = add(32767, mult(tmp_res, sub(min_alpha, 32767)));
*act_count = 0;
move16();
}
/*---------------------------------------------------------*
* calculate lowpass filtered excitation gain
*---------------------------------------------------------*/
Tmp = shr(Exc2_local[0], En_shift);
vare = L_mult(Tmp, Tmp); /* positive accumulation only */
FOR (i=1; i<L_FRAME; i++)
{
Tmp = shr(Exc2_local[i], En_shift);
vare = L_mac(vare, Tmp, Tmp); /* positive accumulation only */
}
/* obtain Ge in Q_local with safety saturation */
L_Ge = L_shl(L_Sqrt_Q0(L_shr(vare,1)),add(sub(*Q_stat_noise_ge,4),En_shift)); /* L_Ge in Q_local*/
/* st->ge_sm = ISP_SMOOTHING_QUANT_A1 * st->ge_sm + (1.0f-ISP_SMOOTHING_QUANT_A1) * ge */
IF ( sub(*uv_count,1) == 0)
{
*ge_sm = L_shr(L_Ge,Q_local);
}
ELSE
{
L_tmp = Mult_32_16(L_Ge,P1); /* 0.1*ge still in Q local */
L_tmp3 = Mult_32_16(*ge_sm,P9); /* 0.9*ge_sm still in Q_ge */
*ge_sm = L_add(L_shr(L_tmp,Q_local),L_tmp3);
move32(); /* addition in Q_ge domain*/
}
/*--------------------------------------------------------------------*
* generate mixture of excitation and noise
* float:
* noimix_fac = 1.0f/(float)sqrt(alpha*alpha + (1-alpha)*(1-alpha))
*--------------------------------------------------------------------*/
beta = shl(sub(alpha, 16384), 1);
alpha_m1 = sub(32767, alpha);
L_tmp_res = L_mac(0, alpha, alpha);
L_tmp_res = L_mac(L_tmp_res, alpha_m1, alpha_m1);
tmp_den = round_fx(L_Frac_sqrtQ31(L_tmp_res));
tmp_nom = sub(32767, tmp_den);
tmp_shift = norm_s(tmp_den);
tmp_den = shl(tmp_den, tmp_shift);
tmp_res = div_s(tmp_nom, tmp_den);
Noimix_fract = shr(tmp_res, tmp_shift); /* float value is in range 0.0 to 0.42 */
/* L_Ge might be 0 in unvoiced WB */
L_Ge = L_max(L_Ge, 1);
tmp_shift = norm_l(L_Ge);
tmp_den = extract_h(L_shl(L_Ge, tmp_shift)); /* Q_local+Q_ge+tmp_shift-16 */
tmp_res = div_s(1<<14, tmp_den); /* 15+14-Q_local-tmp_shift-Q_ge+16 */
L_tmp_res = Mult_32_16(*ge_sm, tmp_res); /* Q_stat_noise_ge+45-Q_local-Q_ge-tmp_shift-15 */
L_tmp_res = Mult_32_16(L_tmp_res, sub(32767, beta)); /*30-Q_local-tmp_shift+15-15 */
L_tmp_res = L_add(L_shl(L_tmp_res, sub(add(Q_local, tmp_shift), 15)), beta); /* Q15 */
tmp_res = extract_h(L_shl(L_tmp_res, 15)); /* 15+15-16=14 */
Noimix_fract = extract_l(Mult_32_16(L_tmp_res, Noimix_fract)); /*15+15-15 */
FOR (i=0; i<L_FRAME; i++)
{
/*--------------------------------------------------------------------*
* flt: exc2[i] = noimix_fac*exc2[i] * alpha + st->ge_sm*Rnd*((1.0f)-alpha)
* flt: exc2[i] = (noimix_fract*exc2[i]+exc2 )* alpha + st->ge_sm*Rnd*((1.0f)-alpha)
* NB: currently uses 32bit accumulation for best low level performance,
* possibly overkill if input is always up-scaled
*--------------------------------------------------------------------*/
/* (1-alpha)*(float)sqrt(12.0f) * ((float)own_random(&(st->noimix_seed))/65536.0f) */
randval = Random(noimix_seed); /* +/-32767 */
randval = mult_r(28378, randval); /* Q downscaled by 2 bits ends up in Q14 */ /*sqrt(12.0f) in Q13*/
randval = extract_l(L_shl(Mult_32_16(L_Ge, randval), 1-*Q_stat_noise_ge)); /*Q_local+Q_ge+14-15+1-Q_ge=Q_local */
L_tmp = L_mult(Exc2_local[i], alpha); /* Q_local + 16 */
L_tmp = L_mac(L_tmp, randval, alpha_m1); /* Q_local + 16 */
L_tmp3 = Mult_32_16(L_tmp, Noimix_fract); /* Q_local+16+15-15 */
L_tmp = L_add(L_tmp3, L_shl(Mult_32_16(L_tmp, tmp_res), 1)); /* Q_local+16+14-15+1 */
Exc2_local[i] = extract_h(L_tmp); /*Q_local */
}
*Q_stat_noise = Q_local; /* update for next call, routine can only be called once every frame */
Qdiff = sub(Q_exc, Q_local); /* local excitation and incoming excitation */
Scale_sig(Exc2_local, L_FRAME, Qdiff);
Copy(Exc2_local, exc2, L_FRAME);
/*--------------------------------------------------------------------*
* Generate low-pass filtered version of ISP coefficients
*--------------------------------------------------------------------*/
FOR (k=0; k<M; k++)
{
move16();
lspnew_s[k] = add(
mult(ISP_SMOOTHING_QUANT_A1_FX, lspold_s[k]),
mult(32767-ISP_SMOOTHING_QUANT_A1_FX, lsp_new[k]));
}
/*--------------------------------------------------------------------*
* replace LPC coefficients
*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*
* pre-calculation of (1-beta)
*--------------------------------------------------------------------*/
FOR (i=0; i<M; i++)
{
move16();
move16();
move16();
oldlsp_mix[i] = add(mult(beta, lsp_old[i]),
mult(sub(32767, beta), lspold_s[i]));
midlsp_mix[i] = add(mult(beta,lsp_mid[i]),
mult(sub(32767, beta), add(shr(lspold_s[i], 1),
shr(lspnew_s[i], 1))));
newlsp_mix[i] = add(mult(beta, lsp_new[i]),
mult(sub(32767, beta),lspnew_s[i]));
}
int_lsp4_fx( L_FRAME, oldlsp_mix, midlsp_mix, newlsp_mix, Aq, M, 0);
Copy(lspnew_s,lspold_s,M);
}
ELSE /* (unvoiced_vad != 0) */
{
(*act_count)++;
IF (sub(*act_count,3) > 0)
{
*act_count = 3;
move16();
*uv_count = 0;
move16();
}
}
}
/*---------------------------------------------------------------------------*
* calc_tilt()
*
* Calculate spectral tilt by means of 1st-order LP analysis
*---------------------------------------------------------------------------*/
static Word16 calc_tilt_fx( /* o : Excitation tilt Q15*/
const Word16 *x, /* i : Signal input */
const Word16 Q_shift, /* i : input scaling */
const Word16 len /* i : lenght */
)
{
Word16 i;
Word16 tmp_shift;
Word32 L_tmp_res;
Word16 tmp_sign,xi,xi_p1;
Word32 r0, r1;
r0 = L_deposit_l(0);
r1 = L_deposit_l(0);
xi = shr(x[0], Q_shift);
move16();
FOR (i=0; i<len-1; i++)
{
/* r0 = L_mac(r0,x[i],x[i]) */
/* r1 = L_mac(r1,x[i],x[i+1]) -> correlation loop can be optimized */
r0 = L_mac(r0,xi,xi);
xi_p1 = shr(x[i+1], Q_shift);
r1 = L_mac(r1, xi, xi_p1);
xi = xi_p1;
move16();
}
if (r0 == 0)
{
r0 = L_shl(327, 16);
}
tmp_shift = norm_l(r0);
move16();
r0 = L_shl(r0,tmp_shift);
tmp_sign = 1;
move16();
if (r1 >= 0)
{
tmp_sign = 0;
move16();
}
r1 = L_abs(r1);
L_tmp_res = Div_32(r1,extract_h(r0), extract_l(r0));
L_tmp_res = L_shl(L_tmp_res, tmp_shift); /*Q31 */
if (tmp_sign != 0)
{
L_tmp_res = L_negate(L_tmp_res); /*Q31 */
}
return extract_h(L_tmp_res); /*Q15 */
}
/*---------------------------------------------------------------------------*
* L_Sqrt_Q0
*
* Calculate square root from fractional values (Q0 -> Q0)
* Uses 32 bit internal representation for precision
*---------------------------------------------------------------------------*/
Word32 L_Sqrt_Q0( /* o : Square root of input */
const Word32 x /* i : Input */
)
{
Word32 log2_work;
Word16 log2_int;
Word16 log2_frac;
IF (x > 0)
{
log2_int = norm_l(x);
log2_frac = Log2_norm_lc(L_shl(x, log2_int));
log2_work = L_mac0(30*32768L, log2_frac, 1);
log2_work = L_msu(log2_work, log2_int, 16384);
log2_frac = L_Extract_lc(log2_work, &log2_int);
return Pow2(log2_int, log2_frac);
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More