- reference source code for EVS codec

This commit is contained in:
Dmytro Bogovych 2018-11-30 13:09:22 +02:00
parent 8c16c048dc
commit 94465da48e
422 changed files with 288315 additions and 0 deletions

View File

View File

@ -0,0 +1,14 @@
project (evscodec)
# Rely on C++ 11
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
file(GLOB_RECURSE EVS_SOURCES "*.cpp" "*.h")
add_library(evs_codec ${EVS_SOURCES})
target_include_directories(evs_codec PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/basic_op
${CMAKE_CURRENT_SOURCE_DIR}/basic_math
${CMAKE_CURRENT_SOURCE_DIR}/lib_enc
${CMAKE_CURRENT_SOURCE_DIR}/lib_dec
${CMAKE_CURRENT_SOURCE_DIR}/lib_com)

View File

@ -0,0 +1,211 @@
/********************************************************************************
*
* File : log2.c
* Purpose : Computes log2(L_x)
*
********************************************************************************
*/
/*
********************************************************************************
* INCLUDE FILES
********************************************************************************
*/
#include "stl.h"
#include "math_op.h"
#include <assert.h>
#include "rom_basic_math.h"
#include "options.h"
#define LW_SIGN (Word32)0x80000000 /* sign bit */
#define LW_MIN (Word32)0x80000000
#define LW_MAX (Word32)0x7fffffff
#define SW_SIGN (Word16)0x8000 /* sign bit for Word16 type */
#define SW_MIN (Word16)0x8000 /* smallest Ram */
#define SW_MAX (Word16)0x7fff /* largest Ram */
/*
********************************************************************************
* PUBLIC PROGRAM CODE
********************************************************************************
*/
/*************************************************************************
*
* FUNCTION: Log2_norm_lc()
*
* PURPOSE: Computes log2(L_x, exp), where L_x is positive and
* normalized, and exp is the normalisation exponent
* If L_x is negative or zero, the result is 0.
*
* DESCRIPTION:
* The function Log2(L_x) is approximated by a table and linear
* interpolation. The following steps are used to compute Log2(L_x)
*
* 1- exponent = 30-norm_exponent
* 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
* 3- a = bit10-b24
* 4- i -=32
* 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
*
*************************************************************************/
Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x /* (i) : input value (normalized) */
)
{
Word16 i, a;
Word16 y;
if (L_x <= 0)
L_x = L_deposit_h(0x4000);
L_x = L_shr (L_x, 9);
a = extract_l (L_x); /* Extract b10-b24 of fraction */
a = lshr(a, 1);
i = mac_r(L_x, -32*2-1, 16384); /* Extract b25-b31 minus 32 */
y = mac_r(L_table_Log2_norm_lc[i], table_diff_Log2_norm_lc[i], a); /* table[i] << 16 - diff*a*2 */
return y;
}
Word32 log10_fx(Word32 Linput)
{
Word16 n1, frac, p1, p2, q1;
Word32 Ltemp1, Ltemp2;
Word32 L_tmp;
if (Linput<=0) return(LW_MIN);
n1=norm_l(Linput);
Ltemp1=(Word32)L_shl(Linput,n1);
Ltemp2=L_mult(extract_h(Ltemp1),0x40);
frac=extract_l(Ltemp2);
p1=log2_tab[sub(extract_h(Ltemp2),0x20)];
p2=log2_tab[sub(extract_h(Ltemp2),0x1F)];
Ltemp2=L_mult(n1,0x200);
n1=extract_l(Ltemp2);
Ltemp1=L_add(L_deposit_h(p1),0x8000); /* Add rounding bit */
IF(frac >= 0)
{
Ltemp1=L_sub(Ltemp1,(Word32)L_mult0(p1,frac));
Ltemp1=L_add(Ltemp1,(Word32)L_mult0(p2,frac));
}
ELSE
{
L_tmp = L_add(65536,frac);
L_tmp = L_tmp*p1;
Ltemp1=L_sub(Ltemp1,L_tmp);
L_tmp = L_add(65536,frac);
L_tmp = L_tmp*p2;
Ltemp1=L_add(Ltemp1,L_tmp);
}
q1=extract_h(Ltemp1);
Ltemp1=L_mult(q1,0x6054);
Ltemp1=L_msu(Ltemp1,0x6054,n1);
return(L_shr(Ltemp1,1));
}
Word32 pow_10(Word32 x , Word16 *Q)
{
Word16 xl,xh, t1, t2, n;
Word32 Ltemp1;
Word32 Lacc;
Word32 L_tmp;
Word16 n1,i;
Word16 count = 0;
move16();;
xl=extract_l(x);
xh=extract_h(x);
IF(xl < 0)
{
L_tmp = L_add(65536,xl);
Ltemp1=(Word32) (0x6a4d*L_tmp );
}
ELSE
{
Ltemp1=L_mult0(0x6a4d,xl);
}
Ltemp1=L_add(L_shr(Ltemp1,16),L_shr(L_mult(xh,0x6a4d),1));
Lacc=L_sub(-1L, Ltemp1); /* Lacc=~Lacc, 1's complement */
t1=extract_l(L_shr(Lacc,7));
Ltemp1=L_shr(Ltemp1,7);
n1 = extract_h(Ltemp1);
n=sub(n1,14);
*Q = 14; move16();
IF(t1<0)
{
L_tmp = L_add(65536,t1);
t2=extract_h(L_tmp*L_tmp);
}
ELSE
{
t2=extract_h(L_mult0(t1,t1));
}
Lacc = L_deposit_h(0x1FEF);
IF(t2 < 0)
{
L_tmp = L_add(65536,t2);
Lacc = L_add(Lacc,(Word32)(L_tmp*0x057C));
}
ELSE
{
Lacc = L_add(Lacc,(Word32)L_mult0(t2,0x057C));
}
IF(t1 < 0)
{
L_tmp = L_add(65536,t1);
Lacc = L_sub(Lacc,(Word32)(L_tmp*0x155C));
}
ELSE
{
Lacc = L_sub(Lacc,(Word32)L_mult0(t1,0x155C));
}
L_tmp = Lacc;
FOR(i =1 ;i <= n ;i++)
{
Overflow = 0; move16();
L_tmp = L_shl(L_tmp,i);
IF(Overflow)
{
count = add(count,1);
}
}
*Q = sub(*Q,count); move16();
return(L_shl(Lacc,sub(n,count)));
}
Word16 Log2_lc( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x, /* (i) : input value */
Word16 *exponent /* (o) : Integer part of Log2. (range: 0<=val<=30) */
)
{
Word16 exp;
if (L_x <= 0)
L_x = L_deposit_l(0x1);
exp = norm_l (L_x);
*exponent = sub(30, exp); move16();
return Log2_norm_lc(L_shl(L_x, exp));
}

View File

@ -0,0 +1,40 @@
/********************************************************************************
*
* File : log2.h
* Purpose : Computes log2(L_x)
*
********************************************************************************
*/
#ifndef log2_h
#define log2_h "$Id $"
/*
********************************************************************************
* INCLUDE FILES
********************************************************************************
*/
#include "typedef.h"
#include "log2.h"
/*
********************************************************************************
* DEFINITION OF DATA TYPES
********************************************************************************
*/
/*
********************************************************************************
* DECLARATION OF PROTOTYPES
********************************************************************************
*/
Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x /* (i) : input value (normalized) */
);
Word32 log10_fx(Word32 Linput);
Word32 pow_10(Word32 x, Word16 *Q);
Word16 Log2_lc( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
Word32 L_x, /* (i) : input value */
Word16 *exponent /* (o) : Integer part of Log2. (range: 0<=val<=30) */
);
#endif

View File

@ -0,0 +1,77 @@
/*#include "options.h" */
#include "stl.h"
#ifdef ALLOW_40bits
#include "enh40.h"
#endif
#include "oper_32b.h"
/* 32x16 multiply: */
Word32 Mult_32_16(Word32 a, Word16 b)
{
Word32 result;
#ifdef ALLOW_40bits /* if activated; need 40 bits basic-op files */
UWord16 lo;
/* use Mpy_32_16_ss(): */
Mpy_32_16_ss(a, b, &result, &lo);
#else
Word16 lo, hi;
/* do things by hand: */
lo = L_Extract_lc(a, &hi);
result = Mpy_32_16(hi, lo, b);
#endif
return result;
}
/* 32x32 multiply: */
Word32 Mult_32_32(Word32 a, Word32 b)
{
Word32 result;
#ifdef ALLOW_40bits /* if activated; need 40 bits basic-op files */
UWord32 lo;
/* use Mpy_32_32_ss(): */
Mpy_32_32_ss(a, b, &result, &lo);
#else
Word16 hi, lo, b_hi, b_lo;
/* do things by hand: */
lo = L_Extract_lc(a, &hi);
b_lo = L_Extract_lc(b, &b_hi);
result = Mpy_32(hi, lo, b_hi, b_lo);
#endif
return result;
}
/* 32x16 multiply-accumulate: */
Word32 Madd_32_16(Word32 L_num, Word32 a, Word16 b)
{
Word32 result;
#ifdef ALLOW_40bits /* if activated; need 40 bits basic-op files */
UWord16 lo;
/* use Mpy_32_16_ss(): */
Mpy_32_16_ss(a, b, &result, &lo);
result = L_add(L_num, result);
#else
Word16 lo, hi;
/* do things by hand: */
lo = L_Extract_lc(a, &hi);
result = Mac_32_16(L_num, hi, lo, b);
#endif
return result;
}
/* 32x16 multiply-substract: */
Word32 Msub_32_16(Word32 L_num, Word32 a, Word16 b)
{
Word32 result;
#ifdef ALLOW_40bits /* if activated; need 40 bits basic-op files */
UWord16 lo;
/* use Mpy_32_16_ss(): */
Mpy_32_16_ss(a, b, &result, &lo);
result = L_sub(L_num, result);
#else
Word16 lo, hi;
/* do things by hand: */
lo = L_Extract_lc(a, &hi);
result = Msu_32_16(L_num, hi, lo, b);
#endif
return result;
}

View File

@ -0,0 +1,12 @@
#ifndef _MATH_32_H_
#define _MATH_32_H_
#include "typedef.h"
#include "basop32.h"
extern Word32 Mult_32_16(Word32 a, Word16 b);
extern Word32 Madd_32_16(Word32 L_num, Word32 a, Word16 b);
extern Word32 Msub_32_16(Word32 L_num, Word32 a, Word16 b);
extern Word32 Mult_32_32(Word32 a, Word32 b);
#endif

View File

@ -0,0 +1,359 @@
/*___________________________________________________________________________
| |
| This file contains mathematic operations in fixed point. |
| |
| Isqrt() : inverse square root (16 bits precision). |
| Pow2() : 2^x (16 bits precision). |
| Log2() : log2 (16 bits precision). |
| Dot_product() : scalar product of <x[],y[]> |
| |
| In this file, the values use theses representations: |
| |
| Word32 L_32 : standard signed 32 bits format |
| Word16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format) |
| Word32 frac, Word16 exp : L_32 = frac << exp-31 (normalised format) |
| Word16 int, frac : L_32 = int.frac (fractional format) |
|___________________________________________________________________________|
*/
#include "stl.h"
#include "math_op.h"
#include "rom_basic_math.h"
#include <stdlib.h>
#include <stdio.h>
/*___________________________________________________________________________
| |
| Function Name : Isqrt |
| |
| Compute 1/sqrt(L_x). |
| if L_x is negative or zero, result is 1 (7fffffff). |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| 1- Normalization of L_x. |
| 2- call Isqrt_lc(L_x, exponant) |
| 3- L_y = L_x << exponant |
|___________________________________________________________________________|
*/
Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
)
{
Word16 exp;
Word32 L_y;
exp = norm_l(L_x);
L_x = L_shl(L_x, exp); /* L_x is normalized */
exp = sub(31, exp);
L_x = Isqrt_lc(L_x, &exp);
L_y = L_shl(L_x, exp); /* denormalization */
return (L_y);
}
/*___________________________________________________________________________
| |
| Function Name : Isqrt_lc |
| |
| Compute 1/sqrt(value). |
| if value is negative or zero, result is 1 (frac=7fffffff, exp=0). |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| The function 1/sqrt(value) is approximated by a table and linear |
| interpolation. |
| |
| 1- If exponant is odd then shift fraction right once. |
| 2- exponant = -((exponant-1)>>1) |
| 3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |
| 4- a = bit10-b24 |
| 5- i -=16 |
| 6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
|___________________________________________________________________________|
*/
Word32 Isqrt_lc(
Word32 frac, /* (i) Q31: normalized value (1.0 < frac <= 0.5) */
Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
)
{
Word16 i, a;
Word32 L_tmp;
IF (frac <= (Word32) 0)
{
*exp = 0; move16();
return 0x7fffffff; /*0x7fffffff*/
}
/* If exponant odd -> shift right by 10 (otherwise 9) */
L_tmp = L_shr(frac, shift_Isqrt_lc[s_and(*exp, 1)]);
/* 1) -16384 to shift left and change sign */
/* 2) 32768 to Add 1 to Exponent like it was divided by 2 */
/* 3) We let the mac_r add another 0.5 because it imitates */
/* the behavior of shr on negative number that should */
/* not be rounded towards negative infinity. */
/* It replaces: */
/* *exp = negate(shr(sub(*exp, 1), 1)); move16(); */
*exp = mac_r(32768, *exp, -16384); move16();
a = extract_l(L_tmp); /* Extract b10-b24 */
a = lshr(a, 1);
i = mac_r(L_tmp, -16*2-1, 16384); /* Extract b25-b31 minus 16 */
L_tmp = L_msu(L_table_isqrt[i], table_isqrt_diff[i], a);/* table[i] << 16 - diff*a*2 */
return L_tmp;
}
/*___________________________________________________________________________
| |
| Function Name : Pow2() |
| |
| L_x = pow(2.0, exponant.fraction) (exponant = interger part) |
| = pow(2.0, 0.fraction) << exponant |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| The function Pow2(L_x) is approximated by a table and linear |
| interpolation. |
| |
| 1- i = bit10-b15 of fraction, 0 <= i <= 31 |
| 2- a = bit0-b9 of fraction |
| 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
| 4- L_x = L_x >> (30-exponant) (with rounding) |
|___________________________________________________________________________|
*/
Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
)
{
Word16 exp, i, a;
Word32 L_x;
i = mac_r(-32768, fraction, 32); /* Extract b10-b16 of fraction */
a = s_and(fraction, 0x3ff); /* Extract b0-b9 of fraction */
L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */
L_x = L_mac(L_x, table_pow2_diff_x32[i], a);/* L_x -= diff*a*2 */
exp = sub(30, exponant);
L_x = L_shr_r(L_x, exp);
return L_x;
}
/*___________________________________________________________________________
| |
| Function Name : Dot_product12() |
| |
| Compute scalar product of <x[],y[]> using accumulator. |
| |
| The result is normalized (in Q31) with exponent (0..30). |
|---------------------------------------------------------------------------|
| Algorithm: |
| |
| dot_product = sum(x[i]*y[i]) i=0..N-1 |
|___________________________________________________________________________|
*/
Word32 Dot_product12( /* (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 */
Word16 * exp /* (o) : exponent of result (0..+30) */
)
{
Word16 i, sft;
Word32 L_sum;
L_sum = L_mac(1, x[0], y[0]);
FOR (i = 1; i < lg; i++)
L_sum = L_mac(L_sum, x[i], y[i]);
/* Normalize acc in Q31 */
sft = norm_l(L_sum);
L_sum = L_shl(L_sum, sft);
*exp = sub(30, sft); move16(); /* exponent = 0..30 */
return L_sum;
}
/*___________________________________________________________________________
| |
| Function Name : Energy_scale() |
| |
| Compute energy of signal (scaling the input if specified) |
| |
| The result is normalized (in Q31) with exponent (0..30). |
|___________________________________________________________________________|
*/
Word32 Energy_scale( /* (o) : Q31: normalized result (1 < val <= -1) */
const Word16 x[], /* (i) : input vector x */
const Word16 lg, /* (i) : vector length */
Word16 expi, /* (i) : exponent of input */
Word16 *exp /* (o) : exponent of result (0..+30) */
)
{
Word16 i, sft, tmp;
Word32 L_sum;
L_sum = 0; /* just to avoid superflous compiler warning about uninitialized use of L_sum */
IF (expi == 0)
{
L_sum = L_mac(1, x[0], x[0]);
FOR (i = 1; i < lg; i++)
{
L_sum = L_mac(L_sum, x[i], x[i]);
}
}
IF (expi < 0)
{
sft = lshl(-32768 /* 0x8000 */, expi);
tmp = mult_r(x[0], sft);
L_sum = L_mac(1, tmp, tmp);
FOR (i = 1; i < lg; i++)
{
tmp = mult_r(x[i], sft);
L_sum = L_mac(L_sum, tmp, tmp);
}
}
IF (expi > 0)
{
tmp = shl(x[0], expi);
L_sum = L_mac(1, tmp, tmp);
FOR (i = 1; i < lg; i++)
{
tmp = shl(x[i], expi);
L_sum = L_mac(L_sum, tmp, tmp);
}
}
/* Normalize acc in Q31 */
sft = norm_l(L_sum);
L_sum = L_shl(L_sum, sft);
*exp = sub(30, sft); move16(); /* exponent = 0..30 */
return L_sum;
}
Word32 Sqrt_l( /* o : output value, Q31 */
Word32 L_x, /* i : input value, Q31 */
Word16 *exp /* o : right shift to be applied to result, Q1 */
)
{
/*
y = sqrt(x)
x = f * 2^-e, 0.5 <= f < 1 (normalization)
y = sqrt(f) * 2^(-e/2)
a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2,
0.707 <= sqrt(f) < 1)
b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2,
0.5 <= sqrt(f/2) < 0.707)
*/
Word16 e, i, a, tmp;
Word32 L_y;
if (L_x <= 0)
{
*exp = 0; move16 ();
return L_deposit_l(0);
}
e = s_and(norm_l(L_x), 0x7FFE); /* get next lower EVEN norm. exp */
L_x = L_shl(L_x, e); /* L_x is normalized to [0.25..1) */
*exp = e; move16 (); /* return 2*exponent (or Q1) */
L_x = L_shr(L_x, 9);
a = extract_l(L_x); /* Extract b10-b24 */
a = lshr(a, 1);
i = mac_r(L_x, -16*2-1, 16384); /* Extract b25-b31 minus 16 */
L_y = L_deposit_h(sqrt_table[i]); /* table[i] << 16 */
tmp = sub(sqrt_table[i], sqrt_table[i + 1]); /* table[i] - table[i+1]) */
L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */
/* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */
return (L_y);
}
/*---------------------------------------------------------------------------*
* L_Frac_sqrtQ31
*
* Calculate square root from fractional values (Q31 -> Q31)
* Uses 32 bit internal representation for precision
*---------------------------------------------------------------------------*/
Word32 L_Frac_sqrtQ31( /* o : Square root if input */
const Word32 x /* i : Input */
)
{
Word32 log2_work;
Word16 log2_int, log2_frac;
test();
if (x > 0)
{
log2_int = norm_l(x);
log2_frac = Log2_norm_lc(L_shl(x, log2_int));
log2_work = L_msu((31+30)*65536L/2, 16384, log2_int);
log2_work = L_mac0(log2_work, log2_frac, 1);
log2_frac = L_Extract_lc(log2_work, &log2_int);
return Pow2(log2_int, log2_frac);
}
return 0;
}
/*----------------------------------------------------------------------------------*
* Frac_sqrt
*
* Calculate square root from fractional values (Q15 -> Q15)
*----------------------------------------------------------------------------------*/
Word16 Frac_sqrt( /* o : Square root if input */
const Word16 x /* i : Input */
)
{
return round_fx(L_Frac_sqrtQ31(L_deposit_h(x)));
}
/*----------------------------------------------------------------------------------*
* i_mult2
*
* Faster Integer Multiplication
*----------------------------------------------------------------------------------*/
Word16 i_mult2 (Word16 a, Word16 b)
{
return extract_l(L_mult0(a, b));
}

View File

@ -0,0 +1,48 @@
/*--------------------------------------------------------------------------*
* MATH_OP.H *
*--------------------------------------------------------------------------*
* Mathematical operations *
*--------------------------------------------------------------------------*/
#include "oper_32b.h"
#include "log2.h"
Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
);
Word32 Isqrt_lc(
Word32 frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
);
Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
);
Word32 Dot_product12( /* (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 */
Word16 * exp /* (o) : exponent of result (0..+30) */
);
Word32 Energy_scale( /* (o) Q31: normalized result (1 < val <= -1) */
const Word16 x[], /* (i) 12bits: x vector */
const Word16 lg, /* (i) : vector length */
Word16 expi, /* (i) : exponent of input */
Word16 *exp /* (o) : exponent of result (0..+30) */
);
Word32 Sqrt_l(Word32 L_x, Word16 *exp);
Word32 L_Frac_sqrtQ31( /* o : Square root if input */
const Word32 x /* i : Input */
);
Word16 Frac_sqrt( /* o : Square root if input */
const Word16 x /* i : Input */
);
Word16 i_mult2 (Word16 a, Word16 b);
#include "math_32.h"

View File

@ -0,0 +1,381 @@
/*****************************************************************************
* $Id: oper_32b.c 1094 2014-02-10 17:12:11Z jdr $
*
* This file contains operations in double precision. *
* These operations are not standard double precision operations. *
* They are used where single precision is not enough but the full 32 bits *
* precision is not necessary. For example, the function Div_32() has a *
* 24 bits precision which is enough for our purposes. *
* *
* The double precision numbers use a special representation: *
* *
* L_32 = hi<<16 + lo<<1 *
* *
* L_32 is a 32 bit integer. *
* hi and lo are 16 bit signed integers. *
* As the low part also contains the sign, this allows fast multiplication. *
* *
* 0x8000 0000 <= L_32 <= 0x7fff fffe. *
* *
* We will use DPF (Double Precision Format) in this file to specify *
* this special format. *
*****************************************************************************
*/
#include "stl.h"
#include "math_op.h"
/*****************************************************************************
* *
* Function L_Extract() *
* *
* Extract from a 32 bit integer two 16 bit DPF. *
* *
* Arguments: *
* *
* L_32 : 32 bit integer. *
* 0x8000 0000 <= L_32 <= 0x7fff ffff. *
* hi : b16 to b31 of L_32 *
* lo : (L_32 - hi<<16)>>1 *
*****************************************************************************
*/
void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
{
*hi = extract_h (L_32);
*lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
return;
}
/*****************************************************************************
* *
* Function L_Extract_lc() *
* *
* Extract from a 32 bit integer two 16 bit DPF. *
* (lo is returned, store to memory is not accounted for) *
* *
* Arguments: *
* *
* L_32 : 32 bit integer. *
* 0x8000 0000 <= L_32 <= 0x7fff ffff. *
* hi : b16 to b31 of L_32 *
* lo : (L_32 - hi<<16)>>1 *
*****************************************************************************
*/
Word16 L_Extract_lc (Word32 L_32, Word16 *hi)
{
*hi = extract_h (L_32);
return lshr(extract_l(L_32), 1);
}
/*****************************************************************************
* *
* Function L_Comp() *
* *
* Compose from two 16 bit DPF a 32 bit integer. *
* *
* L_32 = hi<<16 + lo<<1 *
* *
* Arguments: *
* *
* hi msb *
* lo lsf (with sign) *
* *
* Return Value : *
* *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x8000 0000 <= L_32 <= 0x7fff fff0. *
* *
*****************************************************************************
*/
Word32 L_Comp (Word16 hi, Word16 lo)
{
Word32 L_32;
L_32 = L_deposit_h (hi);
return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */
}
/*****************************************************************************
* Function Mpy_32() *
* *
* Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
* *
* L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
* *
* This operation can also be viewed as the multiplication of two Q31 *
* number and the result is also in Q31. *
* *
* Arguments: *
* *
* hi1 hi part of first number *
* lo1 lo part of first number *
* hi2 hi part of second number *
* lo2 lo part of second number *
* *
*****************************************************************************
*/
Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
{
Word32 L_32;
L_32 = L_mult (hi1, hi2);
L_32 = L_mac (L_32, mult (hi1, lo2), 1);
L_32 = L_mac (L_32, mult (lo1, hi2), 1);
return (L_32);
}
/*****************************************************************************
* Function Mac_32() *
* *
* Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
* Adds a 32 bit integer (non DFP) *
* *
* L_32 = L_num + (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
* *
* This operation can also be viewed as the multiplication of two Q31 *
* number and the result is also in Q31. *
* *
* Arguments: *
* *
* hi1 hi part of first number *
* lo1 lo part of first number *
* hi2 hi part of second number *
* lo2 lo part of second number *
* *
*****************************************************************************
*/
Word32 Mac_32 (Word32 L_num, Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
{
Word32 L_32;
L_32 = L_mac (L_num, hi1, hi2);
L_32 = L_mac (L_32, mult (hi1, lo2), 1);
L_32 = L_mac (L_32, mult (lo1, hi2), 1);
return (L_32);
}
/*****************************************************************************
* Function Sqr_32() *
* *
* Square one 32 bit integer (DPF). The result is divided by 2**31 *
* *
* L_32 = (hi*hi)<<1 + ( (hi*lo)>>15 *2)<<1 *
* *
* This operation can also be viewed as the square of one Q31 *
* number and the result is also in Q31. *
* *
* Arguments: *
* *
* hi1 hi part of first number *
* lo1 lo part of first number *
* hi2 hi part of second number *
* lo2 lo part of second number *
* *
*****************************************************************************
*/
Word32 Sqr_32 (Word16 hi, Word16 lo)
{
Word32 L_32;
L_32 = L_mult (hi, hi);
L_32 = L_mac (L_32, mult (hi, lo), 2);
return (L_32);
}
/*****************************************************************************
* Function Sad_32() *
* *
* Square one 32 bit integer (DPF). The result is divided by 2**31 *
* Adds a 32 bit integer (non DFP) *
* *
* L_32 = L_num + (hi*hi)<<1 + ( (hi*lo)>>15 *2)<<1 *
* *
* This operation can also be viewed as the square of one Q31 *
* number and the result is also in Q31. *
* *
* Arguments: *
* *
* hi1 hi part of first number *
* lo1 lo part of first number *
* hi2 hi part of second number *
* lo2 lo part of second number *
* *
*****************************************************************************
*/
Word32 Sad_32 (Word32 L_num, Word16 hi, Word16 lo)
{
Word32 L_32;
L_32 = L_mac (L_num, hi, hi);
L_32 = L_mac (L_32, mult (hi, lo), 2);
return (L_32);
}
/*****************************************************************************
* Function Mpy_32_16() *
* *
* Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
* by 2**15 *
* *
* *
* L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
* *
* Arguments: *
* *
* hi hi part of 32 bit number. *
* lo lo part of 32 bit number. *
* n 16 bit number. *
* *
*****************************************************************************
*/
Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
{
Word32 L_32;
L_32 = L_mult (hi, n);
L_32 = L_mac (L_32, mult (lo, n), 1);
return (L_32);
}
/*****************************************************************************
* Function Mac_32_16() *
* *
* Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
* by 2**15 *
* Adds a 32 bit integer (non DFP) *
* *
* *
* L_32 = L_num + (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
* *
* Arguments: *
* *
* L_num 32 bit long signed integer (Word32) *
* hi hi part of 32 bit number. *
* lo lo part of 32 bit number. *
* n 16 bit number. *
* *
*****************************************************************************
*/
Word32 Mac_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n)
{
Word32 L_32;
L_32 = L_mac (L_num, hi, n);
L_32 = L_mac (L_32, mult (lo, n), 1);
return (L_32);
}
/*****************************************************************************
* Function Msu_32_16() *
* *
* Substract a 32 bit integer (non DFP) *
* Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
* by 2**15 *
* *
* *
* L_32 = L_num - (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
* *
* Arguments: *
* *
* L_num 32 bit long signed integer (Word32) *
* hi hi part of 32 bit number. *
* lo lo part of 32 bit number. *
* n 16 bit number. *
* *
*****************************************************************************
*/
Word32 Msu_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n)
{
Word32 L_32;
L_32 = L_msu (L_num, hi, n);
L_32 = L_msu (L_32, mult (lo, n), 1);
return (L_32);
}
/*****************************************************************************
* *
* Function Name : Div_32 *
* *
* Purpose : *
* Fractional integer division of two 32 bit numbers. *
* L_num / L_denom. *
* L_num and L_denom must be positive and L_num < L_denom. *
* L_denom = denom_hi<<16 + denom_lo<<1 *
* denom_hi is a normalize number. *
* *
* Inputs : *
* *
* L_num *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x0000 0000 < L_num < L_denom *
* *
* L_denom = denom_hi<<16 + denom_lo<<1 (DPF) *
* *
* denom_hi *
* 16 bit positive normalized integer whose value falls in the *
* range : 0x4000 < hi < 0x7fff *
* denom_lo *
* 16 bit positive integer whose value falls in the *
* range : 0 < lo < 0x7fff *
* *
* Return Value : *
* *
* L_div *
* 32 bit long signed integer (Word32) whose value falls in the *
* range : 0x0000 0000 <= L_div <= 0x7fff ffff. *
* *
* Algorithm: *
* *
* - find = 1/L_denom. *
* First approximation: approx = 1 / denom_hi *
* 1/L_denom = approx * (2.0 - L_denom * approx ) *
* *
* - result = L_num * (1/L_denom) *
*****************************************************************************
*/
Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo)
{
Word16 approx, hi, lo, n_hi, n_lo;
Word32 L_32;
/* First approximation: 1 / L_denom = 1/denom_hi */
approx = div_s ((Word16) 0x3fff, denom_hi);
/* 1/L_denom = approx * (2.0 - L_denom * approx) */
L_32 = Msu_32_16 ((Word32) 0x7fffffffL, denom_hi, denom_lo, approx);
lo = L_Extract_lc (L_32, &hi);
L_32 = Mpy_32_16 (hi, lo, approx);
/* L_num * (1/L_denom) */
lo = L_Extract_lc (L_32, &hi);
n_lo = L_Extract_lc (L_num, &n_hi);
L_32 = Mpy_32 (n_hi, n_lo, hi, lo);
L_32 = L_shl (L_32, 2);
return (L_32);
}

View File

@ -0,0 +1,18 @@
/* Double precision operations */
/* $Id: oper_32b.h 1094 2014-02-10 17:12:11Z jdr $ */
#ifndef _OPER_32b_H
#define _OPER_32b_H
void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
Word16 L_Extract_lc (Word32 L_32, Word16 *hi);
Word32 L_Comp (Word16 hi, Word16 lo);
Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
Word32 Mac_32 (Word32 L_num, Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
Word32 Sqr_32 (Word16 hi, Word16 lo);
Word32 Sad_32 (Word32 L_num, Word16 hi, Word16 lo);
Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
Word32 Mac_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n);
Word32 Msu_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n);
Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo);
#endif

View File

@ -0,0 +1,91 @@
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Decoder static structure */
#include "stl.h"
/* math_op.c */
const Word32 L_table_isqrt[48] =
{
2147418112L, 2083389440L, 2024669184L, 1970667520L,
1920794624L, 1874460672L, 1831403520L, 1791098880L,
1753415680L, 1717960704L, 1684602880L, 1653145600L,
1623326720L, 1595080704L, 1568276480L, 1542782976L,
1518469120L, 1495334912L, 1473183744L, 1451950080L,
1431633920L, 1412169728L, 1393491968L, 1375469568L,
1358168064L, 1341521920L, 1325465600L, 1309933568L,
1294991360L, 1280507904L, 1266548736L, 1252982784L,
1239875584L, 1227161600L, 1214775296L, 1202847744L,
1191182336L, 1179910144L, 1168965632L, 1158283264L,
1147863040L, 1137770496L, 1127940096L, 1118306304L,
1108934656L, 1099825152L, 1090912256L, 1082261504L
};
/* table of table_isqrt[i] - table_isqrt[i+1] */
const Word16 table_isqrt_diff[48] =
{
977, 896, 824, 761, 707, 657, 615, 575,
541, 509, 480, 455, 431, 409, 389, 371,
353, 338, 324, 310, 297, 285, 275, 264,
254, 245, 237, 228, 221, 213, 207, 200,
194, 189, 182, 178, 172, 167, 163, 159,
154, 150, 147, 143, 139, 136, 132, 130
};
const Word16 shift_Isqrt_lc[] = {9,10};
const Word16 table_pow2[32] =
{
16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
31379, 32066
};
/* table of table_pow2[i+1] - table_pow2[i] */
const Word16 table_pow2_diff_x32[32] =
{
11488, 11712, 12000, 12256, 12512, 12800, 13056, 13376, 13664, 13952,
14240, 14560, 14912, 15200, 15552, 15872, 16256, 16576, 16960, 17344,
17696, 18080, 18496, 18880, 19328, 19712, 20192, 20576, 21056, 21536,
21984, 22432
};
const Word16 sqrt_table[49] =
{
16384, 16888, 17378, 17854, 18318, 18770, 19212,
19644, 20066, 20480, 20886, 21283, 21674, 22058,
22435, 22806, 23170, 23530, 23884, 24232, 24576,
24915, 25249, 25580, 25905, 26227, 26545, 26859,
27170, 27477, 27780, 28081, 28378, 28672, 28963,
29251, 29537, 29819, 30099, 30377, 30652, 30924,
31194, 31462, 31727, 31991, 32252, 32511, 32767
};
/* log2.c */
const Word32 L_table_Log2_norm_lc[32] =
{
-32768L, 95322112L, 187793408L, 277577728L,
364871680L, 449740800L, 532381696L, 612859904L,
691306496L, 767787008L, 842432512L, 915308544L,
986546176L, 1056210944L, 1124302848L, 1190887424L,
1256095744L, 1319993344L, 1382580224L, 1443921920L,
1504083968L, 1563131904L, 1621000192L, 1677885440L,
1733722112L, 1788510208L, 1842380800L, 1895399424L,
1947435008L, 1998618624L, 2049015808L, 2098626560L
};
const Word16 table_diff_Log2_norm_lc[32] =
{
1455, 1411, 1370, 1332, 1295, 1261, 1228, 1197,
1167, 1139, 1112, 1087, 1063, 1039, 1016, 995,
975, 955, 936, 918, 901, 883, 868, 852,
836, 822, 809, 794, 781, 769, 757, 744
};
const Word16 log2_tab[33]={
0x7800, 0x782D, 0x785A, 0x7884, 0x78AE, 0x78D6, 0x78FE, 0x7924,
0x794A, 0x796E, 0x7992, 0x79B4, 0x79D6, 0x79F8, 0x7A18, 0x7A38,
0x7A57, 0x7A75, 0x7A93, 0x7AB1, 0x7ACD, 0x7AE9, 0x7B05, 0x7B20,
0x7B3B, 0x7B55, 0x7B6F, 0x7B88, 0x7BA1, 0x7BB9, 0x7BD1, 0x7BE9,
0x7C00
};

View File

@ -0,0 +1,26 @@
#include "options.h" /* Compilation switches */
#include "cnst_fx.h" /* Decoder static structure */
#include "stl.h"
/* math_op.c */
extern const Word32 L_table_isqrt[48];
/* table of table_isqrt[i] - table_isqrt[i+1] */
extern const Word16 table_isqrt_diff[48];
extern const Word16 shift_Isqrt_lc[];
extern const Word16 table_pow2[32];
/* table of table_pow2[i+1] - table_pow2[i] */
extern const Word16 table_pow2_diff_x32[32];
extern const Word16 sqrt_table[49];
/* log2.c */
extern const Word32 L_table_Log2_norm_lc[32];
extern const Word16 table_diff_Log2_norm_lc[32];
extern const Word16 log2_tab[33];

View File

@ -0,0 +1,51 @@
Read-me for ITU-T/UGST Basic Operator Module
(12.November.2004)
=============================================================
COPYRIGHT NOTE: This source code, and all of its derivations,
is subject to the "ITU-T General Public License". Please have
it read in the distribution disk, or in the ITU-T
Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO
CODING STANDARDS".
=============================================================
The ITU-T/UGST Basic Operator module contails the following files:
General:
~~~~~~~~
basop.rme: ....... Read-me file for Basic Operator module (this file)
C code: ('model' directory)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
basop32.c: ....... 16/32 bit basic operators
basop32.h: ....... Prototypes for basop32.c
count.c: ......... Functions for WMOPS computation
count.h: ......... Prototypes for count.c
typedef.h: ....... Data type definitions
typedefs.h: ...... New data type definitions
move.h: .......... Move & miscellaneous legacy operators
control.c: ....... Control operator internal variable decl.
control.h: ....... Control operators
enh1632.c: ....... Enhanced 16/32 bit basic operators
enh1632.h: ....... Prototypes for enh1632.c
enh40.c: ......... 40 bit basic operators
enh40.h: ......... Prototypes for enh40.c
patch.h: ......... Backward compatibility for operator names
stl.h: ........... Main header file
Demos:
~~~~~~
Demo programs are not available for this module.
Makefiles
~~~~~~~~~
Make files are not available for this module.
-- <k-djafarian@ti.com>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/*
===========================================================================
File: BASOP32.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
GLOBAL FUNCTION PROTOTYPES
History:
26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729
basic operator library (based on basic_op.h) and
G.723.1's basop.h.
05.Jul.00 v1.1 Added 32-bit shiftless mult/mac/msub operators
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
norm_s() weight reduced from 15 to 1.
norm_l() weight reduced from 30 to 1.
L_abs() weight reduced from 2 to 1.
L_add() weight reduced from 2 to 1.
L_negate() weight reduced from 2 to 1.
L_shl() weight reduced from 2 to 1.
L_shr() weight reduced from 2 to 1.
L_sub() weight reduced from 2 to 1.
mac_r() weight reduced from 2 to 1.
msu_r() weight reduced from 2 to 1.
mult_r() weight reduced from 2 to 1.
L_deposit_h() weight reduced from 2 to 1.
L_deposit_l() weight reduced from 2 to 1.
L_mls() weight of 5.
div_l() weight of 32.
i_mult() weight of 3.
30 Nov 09 v2.3 round() function is now round_fx().
saturate() is not referencable from outside application
13 Mar 12 Add Overflow2 flag for additional overflow checking.
============================================================================
*/
#ifndef _BASIC_OP_H
#define _BASIC_OP_H
/* #define BASOP_OVERFLOW2 */
/*___________________________________________________________________________
| |
| Constants and Globals |
|___________________________________________________________________________|
*/
extern Flag Overflow, Overflow2;
extern Flag Carry;
#define BASOP_SATURATE_WARNING_ON
#define BASOP_SATURATE_WARNING_OFF
#define BASOP_SATURATE_ERROR_ON
#define BASOP_SATURATE_ERROR_OFF
#define BASOP_CHECK()
#define MAX_32 (Word32)0x7fffffffL
#define MIN_32 (Word32)0x80000000L
#define MAX_16 (Word16)0x7fff
#define MIN_16 (Word16)0x8000
/*___________________________________________________________________________
| |
| Prototypes for basic arithmetic operators |
|___________________________________________________________________________|
*/
Word16 add (Word16 var1, Word16 var2); /* Short add, 1 */
Word16 sub (Word16 var1, Word16 var2); /* Short sub, 1 */
Word16 abs_s (Word16 var1); /* Short abs, 1 */
Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */
Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */
Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */
Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */
Word16 negate (Word16 var1); /* Short negate, 1 */
Word16 extract_h (Word32 L_var1); /* Extract high, 1 */
Word16 extract_l (Word32 L_var1); /* Extract low, 1 */
Word16 round_fx (Word32 L_var1); /* Round, 1 */
Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */
Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */
Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
sat, 1 */
Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
sat, 1 */
Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 1 */
Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 1 */
Word32 L_add_c (Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */
Word32 L_sub_c (Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */
Word32 L_negate (Word32 L_var1); /* Long negate, 1 */
Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 1 */
Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 1 */
Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 1 */
Word16 shr_r (Word16 var1, Word16 var2); /* Shift right with
round, 2 */
Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
rounding, 1 */
Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
rounding, 1 */
Word32 L_deposit_h (Word16 var1); /* 16 bit var1 -> MSB, 1 */
Word32 L_deposit_l (Word16 var1); /* 16 bit var1 -> LSB, 1 */
Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with
round, 3 */
Word32 L_abs (Word32 L_var1); /* Long abs, 1 */
Word32 L_sat (Word32 L_var1); /* Long saturation, 4 */
Word16 norm_s (Word16 var1); /* Short norm, 1 */
Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */
Word16 norm_l (Word32 L_var1); /* Long norm, 1 */
/*
* Additional G.723.1 operators
*/
Word32 L_mls( Word32, Word16 ) ; /* Weight FFS; currently assigned 5 */
Word16 div_l( Word32, Word16 ) ; /* Weight FFS; currently assigned 32 */
Word16 i_mult(Word16 a, Word16 b); /* Weight FFS; currently assigned 3 */
/*
* New shiftless operators, not used in G.729/G.723.1
*/
Word32 L_mult0(Word16 v1, Word16 v2); /* 32-bit Multiply w/o shift 1 */
Word32 L_mac0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Mac w/o shift 1 */
Word32 L_msu0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Msu w/o shift 1 */
#endif /* ifndef _BASIC_OP_H */
/* end of file */

View File

@ -0,0 +1,30 @@
/*
===========================================================================
File: CONTROL.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
CONTROL FLOW OPERATOR INTERNAL VARIABLE DECLARATIONS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
============================================================================
*/
#include "stl.h"
#if WMOPS
int funcId_where_last_call_to_else_occurred;
long funcid_total_wmops_at_last_call_to_else;
int call_occurred = 1;
#endif
/* end of file */

View File

@ -0,0 +1,307 @@
/*
===========================================================================
File: CONTROL.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
CONTROL FLOW OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
============================================================================
*/
#ifndef _CONTROL_H
#define _CONTROL_H
#include "stl.h"
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
#if (WMOPS)
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
/* Technical note :
* The following 3 variables are only used for correct complexity
* evaluation of the following structure :
* IF{
* ...
* } ELSE IF {
* ...
* } ELSE IF {
* ...
* }
* ...
* } ELSE {
* ...
* }
*/
extern int funcId_where_last_call_to_else_occurred;
extern long funcid_total_wmops_at_last_call_to_else;
extern int call_occurred;
#endif /* if WMOPS */
/*****************************************************************************
*
* Function Macros
*
*****************************************************************************/
/*****************************************************************************
*
* Function Name : FOR
*
* Purpose :
*
* The macro FOR should be used instead of the 'for' C statement.
* The complexity is independent of the number of loop iterations that are
* performed.
*
* Complexity weight : 3 (regardless of number of iterations).
*
*****************************************************************************/
#if !(WMOPS)
#define FOR( a) for( a)
#else /* if !(WMOPS) */
#define FOR( a) if( incrFor(), 0); else for( a)
static __inline void incrFor( void) {
multiCounter[currCounter].For++;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : WHILE
*
* Purpose :
*
* The macro WHILE should be used instead of the 'while' C statement.
* The complexity is proportional to the number of loop iterations that
* are performed.
*
* Complexity weight : 4 x 'number of loop iterations'.
*
*****************************************************************************/
#if !(WMOPS)
#define WHILE( a) while( a)
#else /* if !(WMOPS) */
#define WHILE( a) while( incrWhile(), a)
static __inline void incrWhile( void) {
multiCounter[currCounter].While++;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : DO
*
* Purpose :
*
* The macro DO should be used instead of the 'do' C statement.
*
* Complexity weight : 0 (complexity counted by WHILE macro).
*
*****************************************************************************/
#if !(WMOPS)
#define DO do
#else /* if !(WMOPS) */
#define DO do
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : IF
*
* Purpose :
*
* The macro IF should :
*
* - not be used when :
* - the 'if' structure does not have any 'else if' nor 'else' statement
* - and it conditions only one DSP basic operations.
*
* - be used instead of the 'if' C statement in every other case :
* - when there is an 'else' or 'else if' statement,
* - or when the 'if' conditions several DSP basic operations,
* - or when the 'if' conditions a function call.
*
* Complexity weight : 4
*
*****************************************************************************/
#if !(WMOPS)
#define IF( a) if( a)
#else /* if !(WMOPS) */
#define IF( a) if( incrIf(), a)
static __inline void incrIf( void) {
/* Technical note :
* If the "IF" operator comes just after an "ELSE", its counter
* must not be incremented.
*/
if ( (currCounter != funcId_where_last_call_to_else_occurred)
|| (TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else)
|| (call_occurred == 1))
multiCounter[currCounter].If++;
call_occurred = 0;
funcId_where_last_call_to_else_occurred = MAXCOUNTERS;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : ELSE
*
* Purpose :
*
* The macro ELSE should be used instead of the 'else' C statement.
*
* Complexity weight : 4
*
*****************************************************************************/
#if !(WMOPS)
#define ELSE else
#else /* if !(WMOPS) */
#define ELSE else if( incrElse(), 0) ; else
static __inline void incrElse( void) {
multiCounter[currCounter].If++;
/* We keep track of the funcId of the last function
* which used ELSE {...} structure.
*/
funcId_where_last_call_to_else_occurred = currCounter;
/* We keep track of the number of WMOPS of this funcId
* when the ELSE macro was called.
*/
funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation();
/* call_occurred is set to 0, in order to count the next IF (if necessary)
*/
call_occurred=0;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : SWITCH
*
* Purpose :
*
* The macro SWITCH should be used instead of the 'switch' C statement.
*
* Complexity weight : 8
*
*****************************************************************************/
#if !(WMOPS)
#define SWITCH( a) switch( a)
#else /* if !(WMOPS) */
#define SWITCH( a) switch( incrSwitch(), a)
static __inline void incrSwitch( void) {
multiCounter[currCounter].Switch++;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : CONTINUE
*
* Purpose :
*
* The macro CONTINUE should be used instead of the 'continue' C statement.
*
* Complexity weight : 4
*
*****************************************************************************/
#if !(WMOPS)
#define CONTINUE continue
#else /* if !(WMOPS) */
#define CONTINUE if( incrContinue(), 0); else continue
static __inline void incrContinue( void) {
multiCounter[currCounter].Continue++;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : BREAK
*
* Purpose :
*
* The macro BREAK should be used instead of the 'break' C statement.
*
* Complexity weight : 4
*
*****************************************************************************/
#if !(WMOPS)
#define BREAK break
#else /* if !(WMOPS) */
#define BREAK if( incrBreak(), 0) break; else break
static __inline void incrBreak( void) {
multiCounter[currCounter].Break++;
}
#endif /* if !(WMOPS) */
/*****************************************************************************
*
* Function Name : GOTO
*
* Purpose :
*
* The macro GOTO should be used instead of the 'goto' C statement.
*
* Complexity weight : 4
*
*****************************************************************************/
#if !(WMOPS)
#define GOTO goto
#else /* if !(WMOPS) */
#define GOTO if( incrGoto(), 0); else goto
static __inline void incrGoto( void) {
multiCounter[currCounter].Goto++;
}
#endif /* if !(WMOPS) */
#endif /* _CONTROL_H */
/* end of file */

View File

@ -0,0 +1,624 @@
/*
===========================================================================
File: COUNT.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
COMPLEXITY EVALUATION FUNCTIONS
History:
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
norm_s() weight reduced from 15 to 1.
norm_l() weight reduced from 30 to 1.
L_abs() weight reduced from 2 to 1.
L_add() weight reduced from 2 to 1.
L_negate() weight reduced from 2 to 1.
L_shl() weight reduced from 2 to 1.
L_shr() weight reduced from 2 to 1.
L_sub() weight reduced from 2 to 1.
mac_r() weight reduced from 2 to 1.
msu_r() weight reduced from 2 to 1.
mult_r() weight reduced from 2 to 1.
L_deposit_h() weight reduced from 2 to 1.
L_deposit_l() weight reduced from 2 to 1.
March 06 v2.1 Changed to improve portability.
Dec 06 v2.2 Changed to specify frame rate using setFrameRate()
Adding WMOPS_output_avg() for global average computation
L_mls() weight of 5.
div_l() weight of 32.
i_mult() weight of 3.
============================================================================
*/
/*****************************************************************************
*
* This file contains functions for the automatic complexity calculation
*
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stl.h"
#ifdef WMOPS
static double frameRate = FRAME_RATE; /* default value : 10 ms */
#endif /* ifdef WMOPS */
#ifdef WMOPS
/* Global counter variable for calculation of complexity weight */
BASIC_OP multiCounter[MAXCOUNTERS];
int currCounter=0; /* Zero equals global counter */
#endif /* ifdef WMOPS */
#ifdef WMOPS
void setFrameRate(int samplingFreq, int frameLength)
{
if(frameLength > 0)
{
frameRate = samplingFreq / 1000000.0 / frameLength;
}
return;
}
#endif /* ifdef WMOPS */
#ifdef WMOPS
/*
* Below list is used for displaying the code profiling information in
* the file which name is defined by CODE_PROFILE_FILENAME.
* For further details see generic_WMOPS_output() function.
* Attention, the ordering in this table must be kept in synchronisation
* with the structure definition BASIC_OP.
*/
char* BasicOperationList[] =
{
"add", "sub", "abs_s", "shl", "shr",
"extract_h", "extract_l", "mult", "L_mult", "negate",
"round", "L_mac", "L_msu", "L_macNs", "L_msuNs",
"L_add", "L_sub", "L_add_c", "L_sub_c", "L_negate",
"L_shl", "L_shr", "mult_r", "shr_r", "mac_r",
"msu_r", "L_deposit_h", "L_deposit_l", "L_shr_r", "L_abs",
"L_sat", "norm_s", "div_s", "norm_l", "move16",
"move32", "Logic16", "Logic32", "Test", "s_max",
"s_min", "L_max", "L_min", "L40_max", "L40_min",
"shl_r", "L_shl_r", "L40_shr_r", "L40_shl_r", "norm_L40",
"L40_shl", "L40_shr", "L40_negate", "L40_add", "L40_sub",
"L40_abs", "L40_mult", "L40_mac", "mac_r40",
"L40_msu", "msu_r40", "Mpy_32_16_ss", "Mpy_32_32_ss", "L_mult0",
"L_mac0", "L_msu0", "lshl", "lshr", "L_lshl",
"L_lshr", "L40_lshl", "L40_lshr", "s_and", "s_or",
"s_xor", "L_and", "L_or", "L_xor", "rotl",
"rotr", "L_rotl", "L_rotr", "L40_set", "L40_deposit_h",
"L40_deposit_l", "L40_deposit32", "Extract40_H", "Extract40_L", "L_Extract40",
"L40_round", "L_saturate40", "round40", "IF", "GOTO",
"BREAK", "SWITCH", "FOR", "WHILE", "CONTINUE"
, "L_mls", "div_l", "i_mult"
};
#endif /* ifdef WMOPS */
#ifdef WMOPS
const BASIC_OP op_weight =
{
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 2, 2, 1,
1, 1, 1, 3, 1,
1, 1, 1, 3, 1,
4, 1, 18, 1, 1,
2, 1, 2, 2, 1,
1, 1, 1, 1, 1,
3, 3, 3, 3, 1,
1, 1, 1, 1, 1,
1, 1, 1, 2,
1, 2, 2, 4, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 3,
3, 3, 3, 3, 1,
1, 1, 1, 1, 1,
1, 1, 1, 4, 4,
4, 8, 3, 4, 4
, 5, 32, 3
};
#endif /* ifdef WMOPS */
Word32 TotalWeightedOperation (void);
Word32 DeltaWeightedOperation (void);
#ifdef WMOPS
/* Counters for separating counting for different objects */
static int maxCounter=0;
static char* objectName[MAXCOUNTERS+1];
static Word16 fwc_corr[MAXCOUNTERS+1];
static long int nbTimeObjectIsCalled[MAXCOUNTERS+1];
#define NbFuncMax 1024
static Word16 funcid[MAXCOUNTERS], nbframe[MAXCOUNTERS];
static Word32 glob_wc[MAXCOUNTERS], wc[MAXCOUNTERS][NbFuncMax];
static float total_wmops[MAXCOUNTERS];
static Word32 LastWOper[MAXCOUNTERS];
#endif /* ifdef WMOPS */
#ifdef WMOPS
static char* my_strdup(const char *s) {
/*
* duplicates UNIX function strdup() which is not ANSI standard:
* -- malloc() memory area big enough to hold the string s
* -- copy string into new area
* -- return pointer to new area
*
* returns NULL if either s==NULL or malloc() fails
*/
char *dup;
if (s == NULL)
return NULL;
/* allocate memory for copy of ID string (including string terminator) */
/* NOTE: the ID strings will never be deallocated because there is no
way to "destroy" a counter that is not longer needed */
if ((dup = (char *) malloc(strlen(s)+1)) == NULL)
return NULL;
return strcpy(dup, s);
}
#endif /* ifdef WMOPS */
int getCounterId( char *objectNameArg) {
#if WMOPS
if(maxCounter>=MAXCOUNTERS-1) return 0;
objectName[++maxCounter]=my_strdup(objectNameArg);
return maxCounter;
#else /* ifdef WMOPS */
(void)objectNameArg;
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
#if WMOPS
int readCounterId() {
return currCounter;
}
#endif /* ifdef WMOPS */
#ifdef WMOPS
char * readCounterIdName() {
return objectName[currCounter];
}
#endif /* ifdef WMOPS */
void setCounter( int counterId) {
#if WMOPS
if( (counterId > maxCounter)
|| (counterId < 0)) {
currCounter=0;
return;
}
currCounter=counterId;
call_occurred = 1;
#else
(void)counterId;
#endif /* ifdef WMOPS */
}
void incrementNbTimeObjectIsCalled( int counterId) {
#if WMOPS
if( (counterId > maxCounter)
|| (counterId < 0)) {
nbTimeObjectIsCalled[0]++;
return;
}
nbTimeObjectIsCalled[counterId]++;
#else
(void)counterId;
#endif /* ifdef WMOPS */
}
#if WMOPS
static Word32 WMOPS_frameStat() {
/* calculate the WMOPS seen so far and update the global
per-frame maximum (glob_wc)
*/
Word32 tot;
tot = TotalWeightedOperation ();
if (tot > glob_wc[currCounter])
glob_wc[currCounter] = tot;
/* check if fwc() was forgotten at end of last frame */
if (tot > LastWOper[currCounter]) {
if (!fwc_corr[currCounter]) {
fprintf(stderr,
"count: operations counted after last fwc() for '%s'; "
"-> fwc() called\n",
objectName[currCounter]?objectName[currCounter]:"");
}
fwc();
}
return tot;
}
#endif /* ifdef WMOPS */
#ifdef WMOPS
static void WMOPS_clearMultiCounter() {
Word16 i;
Word32 *ptr = (Word32 *) &multiCounter[currCounter];
for( i = 0; i < (Word16)(sizeof (multiCounter[currCounter])/ sizeof (Word32)); i++) {
*ptr++ = 0;
}
}
#endif /* ifdef WMOPS */
void ClearNbTimeObjectsAreCalled() {
#if WMOPS
Word16 i;
for (i = 0; i < (Word16)(sizeof (multiCounter[currCounter])/ sizeof (Word32)); i++) {
nbTimeObjectIsCalled[i] = 0;
}
#endif /* ifdef WMOPS */
}
Word32 TotalWeightedOperation () {
#if WMOPS
Word16 i;
Word32 tot, *ptr, *ptr2;
tot = 0;
ptr = (Word32 *) &multiCounter[currCounter];
ptr2 = (Word32 *) &op_weight;
for (i = 0; i < (Word16)(sizeof (multiCounter[currCounter])/ sizeof (Word32)); i++) {
tot += ((*ptr++) * (*ptr2++));
}
return ((Word32) tot);
#else /* ifdef WMOPS */
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
Word32 DeltaWeightedOperation () {
#if WMOPS
Word32 NewWOper, delta;
NewWOper = TotalWeightedOperation ();
delta = NewWOper - LastWOper[currCounter];
LastWOper[currCounter] = NewWOper;
return (delta);
#else /* ifdef WMOPS */
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
void Init_WMOPS_counter (void) {
#if WMOPS
Word16 i;
/* reset function weight operation counter variable */
for (i = 0; i < NbFuncMax; i++)
wc[currCounter][i] = (Word32) 0;
glob_wc[currCounter] = 0;
nbframe[currCounter] = 0;
total_wmops[currCounter] = 0.0;
/* initially clear all counters */
WMOPS_clearMultiCounter();
LastWOper[currCounter] = 0;
funcid[currCounter] = 0;
/* Following line is useful for incrIf(), see control.h */
call_occurred = 1;
funcId_where_last_call_to_else_occurred=MAXCOUNTERS;
#endif /* ifdef WMOPS */
}
void Reset_WMOPS_counter (void) {
#if WMOPS
Word32 tot = WMOPS_frameStat();
/* increase the frame counter --> a frame is counted WHEN IT BEGINS */
nbframe[currCounter]++;
/* add wmops used in last frame to count, then reset counter */
/* (in first frame, this is a no-op */
total_wmops[currCounter] += (float)( tot * frameRate );
/* clear counter before new frame starts */
WMOPS_clearMultiCounter();
LastWOper[currCounter] = 0;
funcid[currCounter] = 0; /* new frame, set function id to zero */
#endif /* ifdef WMOPS */
}
Word32 fwc (void) {
/* function worst case */
#if WMOPS
Word32 tot;
tot = DeltaWeightedOperation ();
if (tot > wc[currCounter][funcid[currCounter]])
wc[currCounter][funcid[currCounter]] = tot;
funcid[currCounter]++;
return (tot);
#else /* ifdef WMOPS */
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
void WMOPS_output (Word16 dtx_mode) {
#if WMOPS
Word16 i;
Word32 tot, tot_wm, tot_wc;
/* get operations since last reset (or init),
but do not update the counters (except the glob_wc[] maximum)
so output CAN be called in each frame without problems.
The frame counter is NOT updated!
*/
tot = WMOPS_frameStat();
tot_wm = (Word32)(total_wmops[currCounter] + ((float) tot) * frameRate);
fprintf (stdout, "%10s:WMOPS=%.3f",
objectName[currCounter]?objectName[currCounter]:"",
((float) tot) * frameRate);
if (nbframe[currCounter] != 0)
{
fprintf (stdout, " Average=%.3f",
tot_wm / (float) nbframe[currCounter]);
}
fprintf (stdout, " WorstCase=%.3f",
((float) glob_wc[currCounter]) * frameRate);
/* Worst worst case printed only when not in DTX mode */
if (dtx_mode == 0)
{
tot_wc = 0L;
for (i = 0; i < funcid[currCounter]; i++)
tot_wc += wc[currCounter][i];
fprintf (stdout, " WorstWC=%.3f", ((float) tot_wc) * frameRate);
}
fprintf (stdout, " (%d frames)\n", nbframe[currCounter]);
#else
(void)dtx_mode;
#endif /* ifdef WMOPS */
}
void WMOPS_output_avg (Word16 dtx_mode, Word32 *tot_wm, Word16 *num_frames) {
#if WMOPS
Word16 i;
Word32 tot, tot_wc;
/* get operations since last reset (or init),
but do not update the counters (except the glob_wc[] maximum)
so output CAN be called in each frame without problems.
The frame counter is NOT updated!
*/
tot = WMOPS_frameStat();
*tot_wm = (Word32)(total_wmops[currCounter] + ((float) tot) * frameRate);
*num_frames = nbframe[currCounter];
fprintf (stdout, "%10s:WMOPS=%.3f",
objectName[currCounter]?objectName[currCounter]:"",
((float) tot) * frameRate);
if (nbframe[currCounter] != 0)
{
fprintf (stdout, " Average=%.3f",
*tot_wm / (float) nbframe[currCounter]);
}
fprintf (stdout, " WorstCase=%.3f",
((float) glob_wc[currCounter]) * frameRate);
/* Worst worst case printed only when not in DTX mode */
if (dtx_mode == 0)
{
tot_wc = 0L;
for (i = 0; i < funcid[currCounter]; i++)
tot_wc += wc[currCounter][i];
fprintf (stdout, " WorstWC=%.3f", ((float) tot_wc) * frameRate);
}
fprintf (stdout, " (%d frames)\n", nbframe[currCounter]);
#else
(void)dtx_mode;
(void)tot_wm;
(void)num_frames;
#endif /* ifdef WMOPS */
}
void generic_WMOPS_output (Word16 dtx_mode, char *test_file_name)
{
#if WMOPS
int saved_value;
Word16 i;
Word32 tot, tot_wm, tot_wc, *ptr, *ptr2;
Word40 grand_total;
FILE *WMOPS_file;
saved_value = currCounter;
/*Count the grand_total WMOPS so that % ratio per function group
can be displayed. */
grand_total = 0;
for( currCounter = 0; currCounter <= maxCounter; currCounter++) {
tot = WMOPS_frameStat();
grand_total += tot;
}
if( (WMOPS_file=fopen(WMOPS_DATA_FILENAME,"a"))!=NULL) {
printf( "opened file %s in order to print WMOPS for each function group.\n", WMOPS_DATA_FILENAME);
/* Print the file header line. */
fprintf (WMOPS_file, "Test file name\tFunction Name \tFrame\tNb Times Called\tWMOPS\t%% versus grand total");
if (nbframe[saved_value] != 0)
fprintf (WMOPS_file, "\tAverage");
fprintf (WMOPS_file, "\tWorstCase");
/* Worst worst case printed only when not in DTX mode */
if (dtx_mode == 0)
fprintf (WMOPS_file, "\tWorstWC");
fprintf (WMOPS_file, "\n");
/* Print the WMOPS for each Function Group by scanning
all the function groups with currCounter index.*/
for( currCounter = 0; currCounter <= maxCounter; currCounter++) {
fprintf (WMOPS_file, "%s", test_file_name);
fprintf (WMOPS_file, "\t%s",
objectName[currCounter] ? objectName[currCounter] : "");
fprintf (WMOPS_file, "\t%d", nbframe[currCounter]);
tot = WMOPS_frameStat();
tot_wm = (Word32)(total_wmops[currCounter] + ((float) tot) * frameRate);
fprintf (WMOPS_file, "\t\t%ld", nbTimeObjectIsCalled[currCounter]);
fprintf (WMOPS_file, "\t%.6f", ((float) tot) * frameRate);
fprintf (WMOPS_file, "\t%.3f", ((float) tot) / grand_total * 100);
if (nbframe[currCounter] != 0)
fprintf (WMOPS_file, "\t%.3f", tot_wm / (float) nbframe[currCounter]);
fprintf (WMOPS_file, "\t%.3f", ((float) glob_wc[currCounter]) * frameRate);
/* Worst worst case printed only when not in DTX mode */
if (dtx_mode == 0) {
tot_wc = 0L;
for (i = 0; i < funcid[currCounter]; i++)
tot_wc += wc[currCounter][i];
fprintf (WMOPS_file, "\t%.3f", ((float) tot_wc) * frameRate);
}
fprintf (WMOPS_file, "\n");
}
/* Print the file Grand Total line */
fprintf (WMOPS_file, "%s", test_file_name);
fprintf (WMOPS_file, "\tGrand Total");
fprintf (WMOPS_file, "\t%d", nbframe[saved_value]);
fprintf (WMOPS_file, "\t\t%.6f", ((float) grand_total) * frameRate);
fprintf (WMOPS_file, "\t100.000");
fprintf (WMOPS_file, "\n");
fclose(WMOPS_file);
} else
printf( "Can not open file %s for WMOPS editing\n", WMOPS_DATA_FILENAME);
if( (WMOPS_file=fopen(WMOPS_TOTAL_FILENAME,"a"))!=NULL) {
printf( "opened file %s in order to print application's total WMOPS.\n", WMOPS_TOTAL_FILENAME);
fprintf (WMOPS_file, "%s", test_file_name);
fprintf (WMOPS_file, "\tframe=%d", nbframe[currCounter]);
fprintf (WMOPS_file, "\tWMOPS=%.6f", ((float) grand_total) * frameRate);
fprintf (WMOPS_file, "\n");
fclose(WMOPS_file);
} else
printf( "Can not open file %s for WMOPS editing.\n", WMOPS_TOTAL_FILENAME);
if( (WMOPS_file=fopen(CODE_PROFILE_FILENAME,"a"))!=NULL) {
printf( "opened file %s in order to print basic operation distribution statistics.\n", CODE_PROFILE_FILENAME);
/* Print the file header line. */
fprintf (WMOPS_file, "Test file name\tBasic Operation Name\tframe\tWMOPS\t\t%% versus grand total\n");
/* Print the WMOPS for each Basic Operation across all the defined */
/* Function Groups. */
for( i = 0; i <(Word16)(sizeof(op_weight) / sizeof(Word32)); i++) {
fprintf (WMOPS_file, "%-16s", test_file_name);
fprintf (WMOPS_file, "\t%s", BasicOperationList[i]);
fprintf (WMOPS_file, "\t%d", nbframe[0]);
tot = 0;
ptr = (Word32 *) &multiCounter[0] + i;
ptr2 = (Word32 *) &op_weight + i;
for( currCounter = 0; currCounter <= maxCounter; currCounter++) {
tot += ((*ptr) * (*ptr2));
ptr += (sizeof(op_weight) / sizeof(Word32));
}
fprintf (WMOPS_file, "\t%.6f", ((float) tot) * frameRate);
fprintf (WMOPS_file, "\t%.3f", ((float) tot) / grand_total * 100);
fprintf (WMOPS_file, "\n");
}
/* Print the file Grand Total line */
fprintf (WMOPS_file, "%s", test_file_name);
fprintf (WMOPS_file, "\tGrand Total");
fprintf (WMOPS_file, "\t%d", nbframe[saved_value]);
fprintf (WMOPS_file, "\t%.6f", ((float) grand_total) * frameRate);
fprintf (WMOPS_file, "\t100.000");
fprintf (WMOPS_file, "\n");
fclose(WMOPS_file);
} else
printf( "Can not open file %s for basic operations distribution statistic editing\n", CODE_PROFILE_FILENAME);
currCounter = saved_value;
#else
(void)dtx_mode;
(void)test_file_name;
#endif /* ifdef WMOPS */
}
/* end of file */

410
src/libs/libevs/basic_op/count.h Executable file
View File

@ -0,0 +1,410 @@
/*
===========================================================================
File: COUNT.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
PROTOTYPES & DEFINITION FOR COUNTING OPERATIONS
History
09.Aug.1999 V1.0.0 Input to UGST from ETSI AMR (count.h);
26.Jan.2000 V1.1.0 Added counter entries for G.723.1's
L_mls(), div_l(), i_mult() [from basop32.c]
05.Jul.2000 V1.2.0 Added counter entries for 32bit shiftless
operators L_mult0(), L_mac0(), L_msu0()
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
Dec 06 v2.2 Changed to specify frame rate using setFrameRate()
Adding WMOPS_output_avg() for global average computation
L_mls() weight of 5.
div_l() weight of 32.
i_mult() weight of 3.
============================================================================
*/
/******************************************************************************
* Functions for counting operations.
*
* These functions make it possible to measure the wMOPS of a codec.
*
* All functions in this file, and in other *.h files, update a structure so
* that it will be possible to track how many calls to add(), sub(), L_mult()
* ... was made by the code and to estimate the wMOPS (and MIPS) for a certain
* part of the code.
*
* It is also possible to measure the wMOPS separatly for different parts
* of the codec.
*
* This is done by creating a counter group (getCounterId) for each part of
* the code that one wants a seperate measure for. Before a part of the code
* is executed a call to the "setCounter" function is needed to identify
* which counter group to use.
*
* Currently there is a limit of 255 different counter groups.
*
* In the end of this file, there is a piece of code illustrating how the
* functions can be used.
*
******************************************************************************/
#ifndef _COUNT_H
#define _COUNT_H
/* #define WMOPS 1 */ /* enable WMOPS profiling features */
/* #undef WMOPS */ /* disable WMOPS profiling features */
#define MAXCOUNTERS (256)
#define BASOP_sub_start(label)
#define BASOP_sub_end()
#define SUB_WMOPS_INIT(label) BASOP_sub_start(label)
#define END_SUB_WMOPS BASOP_sub_end()
#define BASOP_push_wmops(label)
#define BASOP_pop_wmops()
#define BASOP_end_noprint
#define BASOP_end
#define BASOP_init
int getCounterId( char *objectName);
/*
* Create a counter group, the "objectname" will be used when printing
* statistics for this counter group.
*
* Returns 0 if no more counter groups are available.
*/
int readCounterId(void);
/*
* Returns the current CounterId.
*/
void setCounter( int counterId);
/*
* Defines which counter group to use, default is zero.
*/
char *readCounterIdName(void);
/*
* Returns the current CounterId name.
*/
void incrementNbTimeObjectIsCalled( int counterId);
/*
* This function enables to increment by 1 a counter
* tracking the number of times the application enters a groups of functions.
* If the counterId is not refering to a defined function counter group, then it is
* the default function group (0) which is impacted.
*
*/
void ClearNbTimeObjectsAreCalled(void);
/*
* This function enables to clear to 0 all the counters enabling to
* track the number of times the application enters any groups of functions.
*/
void Init_WMOPS_counter( void);
/*
* Initiates the current counter group.
*/
void Reset_WMOPS_counter( void);
/*
* Resets the current counter group.
*/
void WMOPS_output ( Word16 notPrintWorstWorstCase);
/*
* Prints the statistics to the screen, if the argument is non zero
* the statistics for worst worst case will not be printed. This is typically
* done for dtx frames.
*
*/
void WMOPS_output_avg (Word16 dtx_mode, Word32 *tot_wm, Word16 *num_frames);
/*
* same as WMOPS_output + returns the total wmops counter and the number of frames
* to support the computation of global average.
*
*/
Word32 fwc( void);
/*
* worst worst case counter.
*
* This function calculates the worst possible case that can be reached.
*
* This is done by calling this function for each subpart of the calculations
* for a frame. This function then stores the maximum wMOPS for each part.
*
* The WMOPS_output function add together all parts and presents the sum.
*/
void setFrameRate(int samplingFreq, int frameLength);
/*
* This function can overwrite the value of the frameRate variable that is
* initialized by the FRAME_RATE constant.
*/
#define WMOPS_DATA_FILENAME "wmops_data.txt"
/*
* WMOPS_DATA_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (wMOPS)
* are appended, function group by function group.
*/
#define CODE_PROFILE_FILENAME "code_profile.txt"
/*
* CODE_PROFILE_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (WMOPS)
* are appended, basic operation by basic operation.
*/
#define WMOPS_TOTAL_FILENAME "wmops_total.txt"
/*
* WMOPS_TOTAL_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (WMOPS)
* are printed, globally for the application.
*/
#define FRAME_RATE (0.0001F) /*in this version frame_rate can be overwriten online by the new setFrameRate function */
/* FRAME_RATE of 0.000025 is corresponding to 40ms frame.*/
/* FRAME_RATE of 0.00005 is corresponding to 20ms frame.*/
/* FRAME_RATE of 0.0001 is corresponding to 10ms frame.*/
/*
* FRAME_RATE is the macro defining the calling rate of the
* application to benchmark.
*/
/* Global counter variable for calculation of complexity weight */
typedef struct
{
UWord32 add; /* Complexity Weight of 1 */
UWord32 sub; /* Complexity Weight of 1 */
UWord32 abs_s; /* Complexity Weight of 1 */
UWord32 shl; /* Complexity Weight of 1 */
UWord32 shr; /* Complexity Weight of 1 */
UWord32 extract_h; /* Complexity Weight of 1 */
UWord32 extract_l; /* Complexity Weight of 1 */
UWord32 mult; /* Complexity Weight of 1 */
UWord32 L_mult; /* Complexity Weight of 1 */
UWord32 negate; /* Complexity Weight of 1 */
UWord32 round; /* Complexity Weight of 1 */
UWord32 L_mac; /* Complexity Weight of 1 */
UWord32 L_msu; /* Complexity Weight of 1 */
UWord32 L_macNs; /* Complexity Weight of 1 */
UWord32 L_msuNs; /* Complexity Weight of 1 */
UWord32 L_add; /* Complexity Weight of 1 */
UWord32 L_sub; /* Complexity Weight of 1 */
UWord32 L_add_c; /* Complexity Weight of 2 */
UWord32 L_sub_c; /* Complexity Weight of 2 */
UWord32 L_negate; /* Complexity Weight of 1 */
UWord32 L_shl; /* Complexity Weight of 1 */
UWord32 L_shr; /* Complexity Weight of 1 */
UWord32 mult_r; /* Complexity Weight of 1 */
UWord32 shr_r; /* Complexity Weight of 3 */
UWord32 mac_r; /* Complexity Weight of 1 */
UWord32 msu_r; /* Complexity Weight of 1 */
UWord32 L_deposit_h; /* Complexity Weight of 1 */
UWord32 L_deposit_l; /* Complexity Weight of 1 */
UWord32 L_shr_r; /* Complexity Weight of 3 */
UWord32 L_abs; /* Complexity Weight of 1 */
UWord32 L_sat; /* Complexity Weight of 4 */
UWord32 norm_s; /* Complexity Weight of 1 */
UWord32 div_s; /* Complexity Weight of 18 */
UWord32 norm_l; /* Complexity Weight of 1 */
UWord32 move16; /* Complexity Weight of 1 */
UWord32 move32; /* Complexity Weight of 2 */
UWord32 Logic16; /* Complexity Weight of 1 */
UWord32 Logic32; /* Complexity Weight of 2 */
UWord32 Test; /* Complexity Weight of 2 */
UWord32 s_max; /* Complexity Weight of 1 */
UWord32 s_min; /* Complexity Weight of 1 */
UWord32 L_max; /* Complexity Weight of 1 */
UWord32 L_min; /* Complexity Weight of 1 */
UWord32 L40_max; /* Complexity Weight of 1 */
UWord32 L40_min; /* Complexity Weight of 1 */
UWord32 shl_r; /* Complexity Weight of 3 */
UWord32 L_shl_r; /* Complexity Weight of 3 */
UWord32 L40_shr_r; /* Complexity Weight of 3 */
UWord32 L40_shl_r; /* Complexity Weight of 3 */
UWord32 norm_L40; /* Complexity Weight of 1 */
UWord32 L40_shl; /* Complexity Weight of 1 */
UWord32 L40_shr; /* Complexity Weight of 1 */
UWord32 L40_negate; /* Complexity Weight of 1 */
UWord32 L40_add; /* Complexity Weight of 1 */
UWord32 L40_sub; /* Complexity Weight of 1 */
UWord32 L40_abs; /* Complexity Weight of 1 */
UWord32 L40_mult; /* Complexity Weight of 1 */
UWord32 L40_mac; /* Complexity Weight of 1 */
UWord32 mac_r40; /* Complexity Weight of 2 */
UWord32 L40_msu; /* Complexity Weight of 1 */
UWord32 msu_r40; /* Complexity Weight of 2 */
UWord32 Mpy_32_16_ss; /* Complexity Weight of 2 */
UWord32 Mpy_32_32_ss; /* Complexity Weight of 4 */
UWord32 L_mult0; /* Complexity Weight of 1 */
UWord32 L_mac0; /* Complexity Weight of 1 */
UWord32 L_msu0; /* Complexity Weight of 1 */
UWord32 lshl; /* Complexity Weight of 1 */
UWord32 lshr; /* Complexity Weight of 1 */
UWord32 L_lshl; /* Complexity Weight of 1 */
UWord32 L_lshr; /* Complexity Weight of 1 */
UWord32 L40_lshl; /* Complexity Weight of 1 */
UWord32 L40_lshr; /* Complexity Weight of 1 */
UWord32 s_and; /* Complexity Weight of 1 */
UWord32 s_or; /* Complexity Weight of 1 */
UWord32 s_xor; /* Complexity Weight of 1 */
UWord32 L_and; /* Complexity Weight of 1 */
UWord32 L_or; /* Complexity Weight of 1 */
UWord32 L_xor; /* Complexity Weight of 1 */
UWord32 rotl; /* Complexity Weight of 3 */
UWord32 rotr; /* Complexity Weight of 3 */
UWord32 L_rotl; /* Complexity Weight of 3 */
UWord32 L_rotr; /* Complexity Weight of 3 */
UWord32 L40_set; /* Complexity Weight of 3 */
UWord32 L40_deposit_h; /* Complexity Weight of 1 */
UWord32 L40_deposit_l; /* Complexity Weight of 1 */
UWord32 L40_deposit32; /* Complexity Weight of 1 */
UWord32 Extract40_H; /* Complexity Weight of 1 */
UWord32 Extract40_L; /* Complexity Weight of 1 */
UWord32 L_Extract40; /* Complexity Weight of 1 */
UWord32 L40_round; /* Complexity Weight of 1 */
UWord32 L_saturate40; /* Complexity Weight of 1 */
UWord32 round40; /* Complexity Weight of 1 */
UWord32 If; /* Complexity Weight of 4 */
UWord32 Goto; /* Complexity Weight of 4 */
UWord32 Break; /* Complexity Weight of 4 */
UWord32 Switch; /* Complexity Weight of 8 */
UWord32 For; /* Complexity Weight of 3 */
UWord32 While; /* Complexity Weight of 4 */
UWord32 Continue; /* Complexity Weight of 4 */
UWord32 L_mls; /* Complexity Weight of 6 */
UWord32 div_l; /* Complexity Weight of 32 */
UWord32 i_mult; /* Complexity Weight of 3 */
}
BASIC_OP;
Word32 TotalWeightedOperation( void);
Word32 DeltaWeightedOperation( void);
void generic_WMOPS_output ( Word16 notPrintWorstWorstCase, char *test_file_name);
/*
* This function enable to append :
* - to WMOPS_DATA_FILENAME file, the WMOPS information related
* to the execution of the application, function group by function
* group.
* - to CODE_PROFILE_FILENAME file, the WMOPS information related
* to the execution of the application, basic operation by basic
* operation.
* - to WMOPS_TOTAL_FILENAME file, the total WMOPS information related
* to the execution of the application.
*
* Note that :
* if the files exists, the data will be written at the end of file.
*
* test_file_name : Is a character string referencing each calls to
* generic_WMOPS_output(). Usually, it is the name of a test
* sequence file.
*
* notPrintWorstWorstCase : Same usage as in WMOPS_output().
*/
#if 0
/*
* Example of how count.h could be used.
*
* In the example below it is assumed that the init_OBJECT functions
* does not use any calls to counter.h or basic_op.h. If this is the case
* a call to the function Reset_WMOPS_counter() must be done after each call
* to init_OBJECT if these operations is not to be included in the statistics.
*/
int main(){
int spe1Id,spe2Id,cheId;
/* initiate counters and objects */
spe1Id=getCounterId("Spe 5k8");
setCounter(spe1Id);
Init_WMOPS_counter ();
init_spe1(...);
spe2Id=getCounterId("Spe 12k2");
setCounter(spe2Id);
Init_WMOPS_counter ();
init_spe2(...);
cheId=getCounterId("Channel encoder");
setCounter(cheId);
Init_WMOPS_counter ();
init_che(...);
...
while(data){
test(); /* Note this call to test(); */
if(useSpe1)
setCounter(spe1Id);
else
setCounter(spe2Id);
Reset_WMOPS_counter();
speEncode(...);
WMOPS_output(0); /* Normal routine for displaying WMOPS info */
setCounter(cheId);
Reset_WMOPS_counter();
preChannelInter(...); fwc(); /* Note the call to fwc() for each part*/
convolve(...); fwc(); /* of the channel encoder. */
interleave(...); fwc();
WMOPS_output(0); /* Normal routine for displaying WMOPS info */
}
}
#endif /* #if 0*/
#endif /* _COUNT_H */
/* end of file */

View File

@ -0,0 +1,676 @@
/*
===========================================================================
File: ENH1632.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
============================================================================
*/
/*****************************************************************************
*
* Enhanced 16/32 bit operators :
* s_max()
* s_min()
* L_max()
* L_min()
* shl_r()
* L_shl_r()
* L_mac0()
* L_mult0()
* L_msu0()
* s_and()
* s_or()
* s_xor()
* L_and()
* L_or()
* lshl()
* lshr()
* L_lshl()
* L_lshr()
* rotr()
* rotl()
* L_rotr()
* L_rotl()
*
*****************************************************************************/
/*****************************************************************************
*
* Include-Files
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "stl.h"
#if (WMOPS)
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
/*****************************************************************************
*
* Functions
*
*****************************************************************************/
/*****************************************************************************
*
* Function Name : lshl
*
* Purpose :
*
* Logically shifts left var1 by var2 positions.
* - If var2 is negative, var1 is shifted to the LSBits by (-var2)
* positions with insertion of 0 at the MSBit.
* - If var2 is positive, var1 is shifted to the MSBits by (var2)
* positions.
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value:
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
Word16 lshl( Word16 var1, Word16 var2) {
Word16 var_out=0;
if( var2 < 0) {
var2 = -var2;
var_out = lshr( var1, var2);
#if (WMOPS)
multiCounter[currCounter].lshr--;
#endif /* if WMOPS */
} else {
if( var2 == 0 || var1 == 0) {
var_out = var1;
} else if( var2 >= 16) {
var_out = 0;
} else {
var_out = var1 << var2;
}
}
#if (WMOPS)
multiCounter[currCounter].lshl++;
#endif /* if WMOPS */
BASOP_CHECK();
return( var_out);
}
/*****************************************************************************
*
* Function Name : lshr
*
* Purpose :
*
* Logically shifts right var1 by var2 positions.
* - If var2 is positive, var1 is shifted to the LSBits by (var2)
* positions with insertion of 0 at the MSBit.
* - If var2 is negative, var1 is shifted to the MSBits by (-var2)
* positions.
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value:
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
Word16 lshr( Word16 var1, Word16 var2) {
Word16 var_out;
if( var2 < 0) {
var2 = -var2;
var_out = lshl( var1, var2);
#if (WMOPS)
multiCounter[currCounter].lshl--;
#endif /* if WMOPS */
} else {
if( var2 == 0 || var1 == 0) {
var_out = var1;
} else if( var2 >= 16) {
var_out = 0;
} else {
var_out = var1 >> 1;
var_out = var_out & 0x7fff;
var_out = var_out >> ( var2-1);
}
}
#if (WMOPS)
multiCounter[currCounter].lshr++;
#endif /* if WMOPS */
BASOP_CHECK();
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_lshl
*
* Purpose :
*
* Logically shifts left L_var1 by var2 positions.
* - If var2 is negative, L_var1 is shifted to the LSBits by (-var2)
* positions with insertion of 0 at the MSBit.
* - If var2 is positive, L_var1 is shifted to the MSBits by (var2)
* positions.
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value:
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in
* the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
Word32 L_lshl( Word32 L_var1, Word16 var2) {
Word32 L_var_out=0;
if( var2 < 0) {
var2 = -var2;
L_var_out = L_lshr( L_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L_lshr--;
#endif /* if WMOPS */
} else {
if( var2 == 0 || L_var1 == 0) {
L_var_out = L_var1;
} else if( var2 >= 32) {
L_var_out = 0;
} else {
L_var_out = L_var1 << var2;
}
}
#if (WMOPS)
multiCounter[currCounter].L_lshl++;
#endif /* if WMOPS */
BASOP_CHECK();
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : L_lshr
*
* Purpose :
*
* Logically shifts right L_var1 by var2 positions.
* - If var2 is positive, L_var1 is shifted to the LSBits by (var2)
* positions with insertion of 0 at the MSBit.
* - If var2 is negative, L_var1 is shifted to the MSBits by (-var2)
* positions.
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value:
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in
* the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
Word32 L_lshr( Word32 L_var1, Word16 var2) {
Word32 L_var_out;
if( var2 < 0) {
var2 = -var2;
L_var_out = L_lshl( L_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L_lshl--;
#endif /* if WMOPS */
} else {
if( var2 == 0 || L_var1 == 0) {
L_var_out = L_var1;
} else if( var2 >= 32) {
L_var_out = 0;
} else {
L_var_out = L_var1 >> 1;
L_var_out = L_var_out & 0x7fffffff;
L_var_out = L_var_out >> (var2 - 1);
}
}
#if (WMOPS)
multiCounter[currCounter].L_lshr++;
#endif /* if WMOPS */
BASOP_CHECK();
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : shl_r
*
* Purpose :
*
* Identical to shl( var1, var2) but with rounding. Saturates the result
* in case of underflows or overflows.
*
* Complexity weight : 3
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
Word16 shl_r( Word16 var1, Word16 var2){
Word16 var_out;
if( var2 >= 0) {
var_out = shl( var1, var2);
#if (WMOPS)
multiCounter[currCounter].shl--;
#endif /* if WMOPS */
} else {
var2 = -var2;
var_out = shr_r( var1, var2);
#if (WMOPS)
multiCounter[currCounter].shr_r--;
#endif /* if WMOPS */
}
#if (WMOPS)
multiCounter[currCounter].shl_r++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_shl_r
*
* Purpose :
*
* Same as L_shl( var1, var2) but with rounding. Saturates the result in
* case of underflows or overflows.
*
* Complexity weight : 3
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= var_out <= 0x7fff ffff.
*
*****************************************************************************/
Word32 L_shl_r( Word32 L_var1, Word16 var2) {
Word32 var_out;
if( var2 >= 0) {
var_out = L_shl( L_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L_shl--;
#endif /* if WMOPS */
} else {
var2 = -var2;
var_out = L_shr_r( L_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L_shr_r--;
#endif /* if WMOPS */
}
#if (WMOPS)
multiCounter[currCounter].L_shl_r++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : rotr
*
* Purpose :
*
* Performs a 16-bit logical rotation of var1 by 1 bit to the LSBits. The
* MSBit is set to var2 bit 0. The LSBit of var1 is kept in *var3 bit 0.
*
* Complexity weight : 3
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value must be 0
* or 1.
*
* Outputs :
*
* *var3 Points on a 16 bit short signed integer (Word16) whose
* value will be 0 or 1.
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
Word16 rotr( Word16 var1, Word16 var2, Word16 *var3) {
Word16 var_out;
*var3 = s_and( var1, 0x1);
var_out = s_or( lshr( var1, 1),
lshl( var2, 15));
#if (WMOPS)
multiCounter[currCounter].s_and--;
multiCounter[currCounter].lshl--;
multiCounter[currCounter].lshr--;
multiCounter[currCounter].s_or--;
multiCounter[currCounter].rotr++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : rotl
*
* Purpose :
*
* Performs a 16-bit logical rotation of var1 by 1 bit to the MSBits. The
* LSBit is set to var2 bit 0. The MSBit of var1 is kept in *var3 bit 0.
*
* Complexity weight : 3
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value must be 0
* or 1.
*
* Outputs :
*
* *var3 Points on a 16 bit short signed integer (Word16) whose
* value will be 0 or 1.
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
Word16 rotl( Word16 var1, Word16 var2, Word16 *var3) {
Word16 var_out;
*var3 = lshr( var1, 15);
var_out = s_or( lshl( var1, 1),
s_and( var2, 0x1));
#if (WMOPS)
multiCounter[currCounter].lshr--;
multiCounter[currCounter].s_and--;
multiCounter[currCounter].lshl--;
multiCounter[currCounter].s_or--;
multiCounter[currCounter].rotl++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_rotr
*
* Purpose :
*
* Performs a 32-bit logical rotation of L_var1 by 1 bit to the LSBits. The
* MSBit is set to var2 bit 0. The LSBit of L_var1 is kept in *var3 bit 0.
*
* Complexity weight : 3
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value must be 0
* or 1.
*
* Outputs :
*
* *var3 Points on a 16 bit short signed integer (Word16) whose
* value will be 0 or 1.
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
Word32 L_rotr( Word32 L_var1, Word16 var2, Word16 *var3) {
Word32 L_var_out;
*var3 = s_and( extract_l( L_var1), 0x1);
L_var_out = L_or( L_lshr( L_var1, 1),
L_lshl( L_deposit_l( var2), 31));
#if (WMOPS)
multiCounter[currCounter].extract_l--;
multiCounter[currCounter].s_and--;
multiCounter[currCounter].L_deposit_l--;
multiCounter[currCounter].L_lshl--;
multiCounter[currCounter].L_lshr--;
multiCounter[currCounter].L_or--;
multiCounter[currCounter].L_rotr++;
#endif /* if WMOPS */
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : L_rotl
*
* Purpose :
*
* Performs a 32-bit logical rotation of L_var1 by 1 bit to the MSBits. The
* LSBit is set to var2 bit 0. The MSBit of L_var1 is kept in *var3 bit 0.
*
* Complexity weight : 3
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value must be 0
* or 1.
*
* Outputs :
*
* *var3 Points on a 16 bit short signed integer (Word16) whose
* value will be 0 or 1.
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
Word32 L_rotl( Word32 L_var1, Word16 var2, Word16 *var3) {
Word32 L_var_out;
*var3 = extract_l( L_lshr( L_var1, 31));
L_var_out = L_or( L_lshl( L_var1, 1),
L_deposit_l( s_and( var2, 0x1)));
#if (WMOPS)
multiCounter[currCounter].L_lshr--;
multiCounter[currCounter].extract_l--;
multiCounter[currCounter].s_and--;
multiCounter[currCounter].L_deposit_l--;
multiCounter[currCounter].L_lshl--;
multiCounter[currCounter].L_or--;
multiCounter[currCounter].L_rotl++;
#endif /* if WMOPS */
return( L_var_out);
}
/* end of file */

View File

@ -0,0 +1,545 @@
/*
===========================================================================
File: ENH1632.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
Some counters incrementations were missing (s_and,
s_or, s_xor).
30 Nov 09 v2.3 saturate() removed
============================================================================
*/
#ifndef _ENH1632_H
#define _ENH1632_H
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
#include "stl.h"
#if (WMOPS)
#include "count.h"
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Prototypes for enhanced 16/32 bit arithmetic operators
*
*****************************************************************************/
Word16 shl_r( Word16 var1, Word16 var2);
Word32 L_shl_r( Word32 L_var1, Word16 var2);
Word16 lshl( Word16 var1, Word16 var2);
Word16 lshr( Word16 var1, Word16 var2);
Word32 L_lshl( Word32 L_var1, Word16 var2);
Word32 L_lshr( Word32 L_var1, Word16 var2);
Word16 rotr( Word16 var1, Word16 var2, Word16 *var3);
Word16 rotl( Word16 var1, Word16 var2, Word16 *var3);
Word32 L_rotr( Word32 var1, Word16 var2, Word16 *var3);
Word32 L_rotl( Word32 var1, Word16 var2, Word16 *var3);
/*****************************************************************************
*
* Functions
*
*****************************************************************************/
/*****************************************************************************
*
* Function Name : s_max
*
* Purpose :
*
* Compares var1 and var2 and returns the maximum value.
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= var1 <= 0x7fff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= var2 <= 0x7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= L_var_out <= 0x7fff.
*
*****************************************************************************/
static __inline Word16 s_max( Word16 var1, Word16 var2) {
Word16 var_out;
if( var1 >= var2)
var_out = var1;
else
var_out = var2;
#if (WMOPS)
multiCounter[currCounter].s_max++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : s_min
*
* Purpose :
*
* Compares var1 and var2 and returns the minimum value.
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= var1 <= 0x7fff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= var2 <= 0x7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value falls in
* the range : 0x8000 <= var_out <= 0x7fff.
*
*****************************************************************************/
static __inline Word16 s_min( Word16 var1, Word16 var2) {
Word16 var_out;
if( var1 <= var2)
var_out = var1;
else
var_out = var2;
#if (WMOPS)
multiCounter[currCounter].s_min++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_max
*
* Purpose :
*
* Compares L_var1 and L_var2 and returns the maximum value.
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
static __inline Word32 L_max( Word32 L_var1, Word32 L_var2) {
Word32 L_var_out;
if( L_var1 >= L_var2)
L_var_out = L_var1;
else
L_var_out = L_var2;
#if (WMOPS)
multiCounter[currCounter].L_max++;
#endif /* if WMOPS */
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : L_min
*
* Purpose :
*
* Compares L_var1 and L_var2 and returns the minimum value.
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
static __inline Word32 L_min( Word32 L_var1, Word32 L_var2) {
Word32 L_var_out;
if( L_var1 <= L_var2)
L_var_out = L_var1;
else
L_var_out = L_var2;
#if (WMOPS)
multiCounter[currCounter].L_min++;
#endif /* if WMOPS */
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : s_and
*
* Purpose :
*
* Performs logical AND of the two 16 bit input variables.
* var_out = var1 & var2
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
static __inline Word16 s_and( Word16 var1, Word16 var2) {
Word16 var_out;
var_out = var1 & var2;
#if (WMOPS)
multiCounter[currCounter].s_and++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_and
*
* Purpose :
*
* Performs logical AND of the two 32 bit input variables.
* L_var_out = L_var1 & L_var2
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
static __inline Word32 L_and( Word32 L_var1, Word32 L_var2) {
Word32 L_var_out;
L_var_out = L_var1 & L_var2;
#if (WMOPS)
multiCounter[currCounter].L_and++;
#endif /* if WMOPS */
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : s_or
*
* Purpose :
*
* Performs logical OR of the two 16 bit input variables.
* var_out = var1 | var2
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
static __inline Word16 s_or( Word16 var1, Word16 var2) {
Word16 var_out;
var_out = var1 | var2;
#if (WMOPS)
multiCounter[currCounter].s_or++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_or
*
* Purpose :
*
* Performs logical OR of the two 32 bit input variables.
* L_var_out = L_var1 | L_var2
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
static __inline Word32 L_or( Word32 L_var1, Word32 L_var2) {
Word32 L_var_out;
L_var_out = L_var1 | L_var2;
#if (WMOPS)
multiCounter[currCounter].L_or++;
#endif /* if WMOPS */
return( L_var_out);
}
/*****************************************************************************
*
* Function Name : s_xor
*
* Purpose :
*
* Performs logical XOR of the two 16 bit input variables.
* var_out = var1 ^ var2
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
*
* var2 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short signed integer (Word16) whose value
* falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
*
*****************************************************************************/
static __inline Word16 s_xor( Word16 var1, Word16 var2) {
Word16 var_out;
var_out = var1 ^ var2;
#if (WMOPS)
multiCounter[currCounter].s_xor++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L_xor
*
* Purpose :
*
* Performs logical OR of the two 32 bit input variables.
* L_var_out = L_var1 ^ L_var2
*
* Complexity weight : 1
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long signed integer (Word32) whose value
* falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
*
*****************************************************************************/
static __inline Word32 L_xor( Word32 L_var1, Word32 L_var2) {
Word32 L_var_out;
L_var_out = L_var1 ^ L_var2;
#if (WMOPS)
multiCounter[currCounter].L_xor++;
#endif /* if WMOPS */
return( L_var_out);
}
#endif /*_ENH1632_H*/
/* end of file */

View File

@ -0,0 +1,688 @@
/*
===========================================================================
File: ENH40.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
40-BIT ARITHMETIC OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
31 Mar 15 v2.1E Removal of operators not used in the EVS codec.
============================================================================
*/
/*****************************************************************************
*
* Enhanced 40 bit operators :
*
* Mpy_32_16_ss()
* Mpy_32_32_ss()
*
*****************************************************************************/
/*****************************************************************************
*
* Include-Files
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "stl.h"
#if (WMOPS)
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Local Functions
*
*****************************************************************************/
static __inline Word40 L40_shr( Word40 L40_var1, Word16 var2);
static __inline Word40 L40_shl( Word40 L40_var1, Word16 var2);
static __inline Word40 L40_set( Word40 L40_var1);
static __inline UWord16 Extract40_L( Word40 L40_var1);
static __inline Word40 L40_mult( Word16 var1, Word16 var2);
static __inline Word40 L40_add( Word40 L40_var1, Word40 L40_var2);
static __inline Word40 L40_mac( Word40 L40_var1, Word16 var2, Word16 var3);
static __inline UWord32 L_Extract40( Word40 L40_var1) ;
/*****************************************************************************
*
* Macros for 40 bit arithmetic overflow management :
* Upon 40-bit overflow beyond MAX_40 or underflow beyond MIN_40,
* the application will exit.
*
*****************************************************************************/
#define L40_OVERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(1), L40_var1)
#define L40_UNDERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(2), L40_var1)
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
/*****************************************************************************
*
* Functions
*
*****************************************************************************/
/*****************************************************************************
*
* Function Name : Mpy_32_16_ss
*
* Purpose :
*
* Multiplies the 2 signed values L_var1 and var2 with saturation control
* on 48-bit. The operation is performed in fractional mode :
* - L_var1 is supposed to be in 1Q31 format.
* - var2 is supposed to be in 1Q15 format.
* - The result is produced in 1Q47 format : L_varout_h points to the
* 32 MSBits while varout_l points to the 16 LSBits.
*
* Complexity weight : 2
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
*
* Outputs :
*
* *L_varout_h 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
*
* *varout_l 16 bit short unsigned integer (UWord16) whose value falls in
* the range : 0x0000 0000 <= varout_l <= 0x0000 ffff.
*
* Return Value :
*
* none
*
*****************************************************************************/
void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l) {
Word16 var1_h;
UWord16 uvar1_l;
Word40 L40_var1;
if( (L_var1 == ( Word32) 0x80000000)
&& (var2 == ( Word16) 0x8000)) {
*L_varout_h = 0x7fffffff;
*varout_l = ( UWord16) 0xffff;
} else {
uvar1_l = extract_l( L_var1);
var1_h = extract_h( L_var1);
/* Below line can not overflow, so we can use << instead of L40_shl. */
L40_var1 = (( Word40) (( Word32) var2 * ( Word32) uvar1_l)) << 1;
*varout_l = Extract40_L( L40_var1);
L40_var1 = L40_shr( L40_var1, 16);
L40_var1 = L40_mac( L40_var1, var2, var1_h);
*L_varout_h = L_Extract40( L40_var1);
#if (WMOPS)
multiCounter[currCounter].extract_l--;
multiCounter[currCounter].extract_h--;
multiCounter[currCounter].Extract40_L--;
multiCounter[currCounter].L40_shr--;
multiCounter[currCounter].L40_mac--;
multiCounter[currCounter].L_Extract40--;
#endif /* if WMOPS */
}
#if (WMOPS)
multiCounter[currCounter].Mpy_32_16_ss++;
#endif /* if WMOPS */
return;
}
/*****************************************************************************
*
* Function Name : Mpy_32_32_ss
*
* Purpose :
*
* Multiplies the 2 signed values L_var1 and L_var2 with saturation control
* on 64-bit. The operation is performed in fractional mode :
* - L_var1 and L_var2 are supposed to be in 1Q31 format.
* - The result is produced in 1Q63 format : L_varout_h points to the
* 32 MSBits while L_varout_l points to the 32 LSBits.
*
* Complexity weight : 4
*
* Inputs :
*
* L_var1 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
*
* L_var2 32 bit long signed integer (Word32) whose value falls in the
* range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
*
* Outputs :
*
* *L_varout_h 32 bit long signed integer (Word32) whose value falls in
* the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
*
* *L_varout_l 32 bit short unsigned integer (UWord32) whose value falls in
* the range : 0x0000 0000 <= L_varout_l <= 0xffff ffff.
*
*
* Return Value :
*
* none
*
*****************************************************************************/
void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l) {
UWord16 uvar1_l, uvar2_l;
Word16 var1_h, var2_h;
Word40 L40_var1;
if( (L_var1 == ( Word32)0x80000000)
&& (L_var2 == ( Word32)0x80000000)) {
*L_varout_h = 0x7fffffff;
*L_varout_l = ( UWord32)0xffffffff;
} else {
uvar1_l = extract_l( L_var1);
var1_h = extract_h( L_var1);
uvar2_l = extract_l( L_var2);
var2_h = extract_h( L_var2);
/* Below line can not overflow, so we can use << instead of L40_shl. */
L40_var1 = (( Word40) (( UWord32) uvar2_l * ( UWord32) uvar1_l)) << 1;
*L_varout_l = 0x0000ffff & L_Extract40( L40_var1);
L40_var1 = L40_shr( L40_var1, 16);
L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var2_h * ( Word32) uvar1_l)) << 1);
L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var1_h * ( Word32) uvar2_l)) << 1);
*L_varout_l |= (L_Extract40( L40_var1)) << 16;
L40_var1 = L40_shr( L40_var1, 16);
L40_var1 = L40_mac( L40_var1, var1_h, var2_h);
*L_varout_h = L_Extract40( L40_var1);
#if (WMOPS)
multiCounter[currCounter].extract_l-=2;
multiCounter[currCounter].extract_h-=2;
multiCounter[currCounter].L_Extract40-=3;
multiCounter[currCounter].L40_shr-=2;
multiCounter[currCounter].L40_add-=2;
multiCounter[currCounter].L40_mac--;
#endif /* if WMOPS */
}
#if (WMOPS)
multiCounter[currCounter].Mpy_32_32_ss++;
#endif /* if WMOPS */
return;
}
/*****************************************************************************
*
* Function Name : L40_set
*
* Purpose :
*
* Assigns a 40 constant to a Word40 with adequate initialization depending
* on underlying architecture constraints (for example to keep consistency
* of sign bits). Current implementation only validated on MSVC++6.0.
*
* Complexity weight : 3
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
/*#ifdef _MSC_VER*/
static __inline Word40 L40_set( Word40 L40_var1) {
Word40 L40_var_out;
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
L40_var_out = L40_var1 & 0x000000ffffffffff;
if( L40_var1 & 0x8000000000)
L40_var_out = L40_var_out | 0xffffff0000000000;
#else
L40_var_out = L40_var1 & 0x000000ffffffffffLL;
if( L40_var1 & 0x8000000000LL)
L40_var_out = L40_var_out | 0xffffff0000000000LL;
#endif
#if WMOPS
multiCounter[currCounter].L40_set++;
#endif /* if WMOPS */
return( L40_var_out);
}
/*#endif*/ /* ifdef _MSC_VER */
/*****************************************************************************
*
* Function Name : Extract40_L
*
* Purpose :
*
* Returns the bits [15-0] of L40_var1.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* Outputs :
*
* none
*
* Return Value :
*
* var_out 16 bit short unsigned integer (UWord16) whose value falls in
* the range : MIN_U_16 <= var_out <= MAX_U_16.
*
*****************************************************************************/
static __inline UWord16 Extract40_L( Word40 L40_var1) {
UWord16 var_out;
var_out = ( UWord16)( L40_var1);
#if (WMOPS)
multiCounter[currCounter].Extract40_L++;
#endif /* if WMOPS */
return( var_out);
}
/*****************************************************************************
*
* Function Name : L40_mult
*
* Purpose :
*
* Multiplies var1 by var2 and shifts the result left by 1. Returns the
* full precision result on 40-bit.
* L40_mult( var1, var2) = shiftleft(( var1 times var2), 1)
*
* Complexity weight : 1
*
* Inputs :
*
* var1 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var1 <= MAX_16.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var2 <= MAX_16.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
static __inline Word40 L40_mult( Word16 var1, Word16 var2) {
Word32 L_var_out;
Word40 L40_var_out;
L_var_out = ( Word32) var1 * ( Word32) var2;
L40_var_out = ( Word40) L_var_out;
/* Below line can not overflow, so we can use << instead of L40_shl. */
L40_var_out = L40_var_out << 1;
#if (WMOPS)
multiCounter[currCounter].L40_mult++;
#endif /* if WMOPS */
return( L40_var_out);
}
/*****************************************************************************
*
* Function Name : L40_add
*
* Purpose :
*
* Adds L40_var1 and L40_var2 and returns the 40-bit result.
* Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
* Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* L40_var2 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var2 <= MAX_40.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
static __inline Word40 L40_add( Word40 L40_var1, Word40 L40_var2) {
Word40 L40_var_out;
L40_var_out = L40_var1 + L40_var2;
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
if( ((( L40_var1 & 0x8000000000) >> 39) != 0)
&& ((( L40_var2 & 0x8000000000) >> 39) != 0)
&& ((( L40_var_out & 0x8000000000) >> 39) == 0)) {
L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out);
} else if( (((L40_var1 & 0x8000000000) >> 39) == 0)
&& (((L40_var2 & 0x8000000000) >> 39) == 0)
&& (((L40_var_out & 0x8000000000) >> 39) != 0)) {
L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out);
}
#else
if( ((( L40_var1 & 0x8000000000LL) >> 39) != 0)
&& ((( L40_var2 & 0x8000000000LL) >> 39) != 0)
&& ((( L40_var_out & 0x8000000000LL) >> 39) == 0)) {
L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out);
} else if( (((L40_var1 & 0x8000000000LL) >> 39) == 0)
&& (((L40_var2 & 0x8000000000LL) >> 39) == 0)
&& (((L40_var_out & 0x8000000000LL) >> 39) != 0)) {
L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out);
}
#endif
#if (WMOPS)
multiCounter[currCounter].L40_add++;
#endif /* if WMOPS */
BASOP_CHECK();
return( L40_var_out);
}
/*****************************************************************************
*
* Function Name : L40_mac
*
* Purpose :
*
* Multiplies var2 by var3. Shifts left the 40-bit result by 1 and adds
* the result to L40_var1. Returns a 40 bit result.
* L40_mac( L40_var1, var2, var3)
* = L40_add( L40_var1, L40_mult( var2, var3))
* Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
* Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var2 <= MAX_16.
*
* var3 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var3 <= MAX_16.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
static __inline Word40 L40_mac( Word40 L40_var1, Word16 var2, Word16 var3) {
Word40 L40_var_out;
L40_var_out = L40_mult( var2, var3);
L40_var_out = L40_add( L40_var1, L40_var_out);
#if (WMOPS)
multiCounter[currCounter].L40_mult--;
multiCounter[currCounter].L40_add--;
multiCounter[currCounter].L40_mac++;
#endif /* if WMOPS */
return( L40_var_out);
}
/*****************************************************************************
*
* Function Name : L_Extract40
*
* Purpose :
*
* Returns the bits [31-0] of L40_var1.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* Outputs :
*
* none
*
* Return Value :
*
* L_var_out 32 bit long unsigned integer (UWord32) whose value falls in
* range : MIN_U_32 <= L_var_out <= MAX_U_32.
*
*****************************************************************************/
static __inline UWord32 L_Extract40( Word40 L40_var1) {
UWord32 L_var_out;
L_var_out = ( UWord32) L40_var1;
#if (WMOPS)
multiCounter[currCounter].L_Extract40++;
#endif /* if WMOPS */
return(L_var_out);
}
/*****************************************************************************
*
* Function Name : L40_shl
*
* Purpose :
*
* Arithmetically shifts left L40_var1 by var2 positions.
* - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2)
* positions with extension of the sign bit.
* - If var2 is positive, L40_var1 is shifted to the MSBits by (var2)
* positions.
* Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
* Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var2 <= MAX_16.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
static __inline Word40 L40_shl( Word40 L40_var1, Word16 var2) {
Word40 L40_var_out;
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
Word40 L40_constant = L40_set( 0xc000000000);
#else
Word40 L40_constant = L40_set( 0xc000000000LL);
#endif
if( var2 < 0) {
var2 = -var2;
L40_var_out = L40_shr( L40_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L40_shr--;
#endif /* if WMOPS */
}
else {
L40_var_out = L40_var1;
for ( ; var2 > 0; var2--) {
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
if( L40_var_out > 0x003fffffffff) {
#else
if( L40_var_out > 0x003fffffffffLL) {
#endif
L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out);
break;
}
else if ( L40_var_out < L40_constant) {
L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out);
break;
}
else {
L40_var_out = L40_var_out << 1;
}
}
}
#if (WMOPS)
multiCounter[currCounter].L40_set--;
multiCounter[currCounter].L40_shl++;
#endif /* if WMOPS */
BASOP_CHECK();
return( L40_var_out);
}
/*****************************************************************************
*
* Function Name : L40_shr
*
* Purpose :
*
* Arithmetically shifts right L40_var1 by var2 positions.
* - If var2 is positive, L40_var1 is shifted to the LSBits by (var2)
* positions with extension of the sign bit.
* - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2)
* positions.
* Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
* Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
*
* Complexity weight : 1
*
* Inputs :
*
* L40_var1 40 bit long signed integer (Word40) whose value falls in the
* range : MIN_40 <= L40_var1 <= MAX_40.
*
* var2 16 bit short signed integer (Word16) whose value falls in
* the range : MIN_16 <= var2 <= MAX_16.
*
* Outputs :
*
* none
*
* Return Value :
*
* L40_var_out 40 bit long signed integer (Word40) whose value falls in
* the range : MIN_40 <= L40_var_out <= MAX_40.
*
*****************************************************************************/
static __inline Word40 L40_shr( Word40 L40_var1, Word16 var2) {
Word40 L40_var_out;
if( var2 < 0) {
var2 = -var2;
L40_var_out = L40_shl ( L40_var1, var2);
#if (WMOPS)
multiCounter[currCounter].L40_shl--;
#endif /* if WMOPS */
} else {
L40_var_out = L40_var1 >> var2;
}
#if (WMOPS)
multiCounter[currCounter].L40_shr++;
#endif /* if WMOPS */
return( L40_var_out);
}
/* end of file */

View File

@ -0,0 +1,44 @@
/*
===========================================================================
File: ENH40.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
40-BIT ARITHMETIC OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
31 Mar 15 v2.1E Removal of operators not used in the EVS codec.
============================================================================
*/
#ifndef _ENH40_H
#define _ENH40_H
#include "stl.h"
/*****************************************************************************
*
* Prototypes for enhanced 40 bit arithmetic operators
*
*****************************************************************************/
void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l);
void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l);
#endif /*_ENH40_H*/
/* end of file */

View File

@ -0,0 +1,430 @@
/*
===========================================================================
File: ENHUL32.C v.0.5 - 21.March.2014
===========================================================================
ENHANCED UNSIGNED 32-BIT ARITHMETIC OPERATORS
History:
============================================================================
*/
/*****************************************************************************
*
* Enhanced Unsigned 32 bit operators :
* see complete list in .h file
*
*****************************************************************************/
/*****************************************************************************
*
* Include-Files
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "stl.h"
#include "enhUL32.h"
#if (WMOPS)
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
/*****************************************************************************
*
* Functions
*
*****************************************************************************/
#ifdef ENHUL32
/*___________________________________________________________________________
| |
| Function Name : UL_deposit_l |
| |
| Purpose : |
| |
| Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The |
| 16 MS bits of the output are not sign extended. |
| |
|___________________________________________________________________________ */
UWord32 UL_deposit_l(UWord16 uvar){
UWord32 UL_result;
UL_result = (UWord32)uvar; /* no sign extension*/
#if (WMOPS)
multiCounter[currCounter].L_deposit_l++;
#endif
return (UL_result);
}
/*___________________________________________________________________________
| |
| Function Name : norm_ul |
| |
| Purpose : |
| |
| Produces the number of left shifts needed to normalize the 32 bit varia-|
| ble UL_var1 for positive values on the interval with minimum of |
| 0 and maximum of 0xffffffff, ; in order to normalize the |
| result, the following operation must be done : |
| |
| norm_UL_var1 = UL_lshl(UL_var1, norm_ul(UL_var1)). |
| |
| Complexity weight : 1 |
| |
| Inputs : |
| |
| UL_var1 |
| 32 bit long unsigned integer (UWord32) whose value falls in the |
| range : 0x0000 0000 <= var1 <= 0xffff ffff. |
| |
| Outputs : |
| |
| none |
| |
| Return Value : |
| |
| var_out |
| 16 bit short signed integer (Word16) whose value falls in the |
| range : 0x0000 0000 <= var_out <= 0x0000 001f. (0..31d) |
|___________________________________________________________________________|
*/
Word16 norm_ul( UWord32 UL_var1)
{
Word16 var_out;
if (UL_var1 == 0)
{
var_out = 0;
}
else
{
/* simply test shift up until highest bit is set */
for (var_out = 0; UL_var1 < (UWord32) 0x80000000U; var_out++)
{
UL_var1 <<= 1;
}
}
#if (WMOPS)
multiCounter[currCounter].norm_l++; /* now new counter added for UL_ */
#endif
return (var_out);
}
/*___________________________________________________________________________
| |
| Function Name : UL_addNs |
| |
| Purpose : |
| |
| 32 bits addition of the two unsigned 32 bits variables |
| (L_var1+L_var2) with overflow control, but without saturation |
|
| Outputs : |
| *wrap = 1 if wrap occured, otherwize 0 |
|
| Return Value :
| UL_var3 = modulo(UL_var1+UL_var2,32)
|___________________________________________________________________________|
*/
UWord32 UL_addNs(UWord32 UL_var1, UWord32 UL_var2, UWord16 * wrap )
{
UWord32 UL_var3;
/* STL Overflow flag is not updated */
UL_var3 = UL_var1 + UL_var2; /* 32bit wrap may occur, like in C */
if ( ( ((UWord64)UL_var1 + (UWord64)UL_var2) ) > ((UWord64) maxUWord32 ) )
{
*wrap = 1; /* wrapped output */
}
else
{
*wrap = 0;
}
#if WMOPS
multiCounter[currCounter].L_add++; /* now new counter added for UL_ */
#endif
return UL_var3;
}
/*___________________________________________________________________________
| |
| Function Name : UL_subNs |
| |
| Purpose : |
| |
| 32 bits subtraction of the two unsigned 32 bits variables |
| (L_var1-L_var2) with overflow control, but without saturation |
|
| Outputs : |
| *sgn = 1 if wrap (to "negative" occured, otherwise 0 |
|
| Return Value :
| UL_var3 = modulo(UL_var1-UL_var2,32)
|___________________________________________________________________________|
*/
UWord32 UL_subNs(UWord32 UL_var1, UWord32 UL_var2, UWord16 * sgn)
{
UWord32 UL_var3;
UL_var3 = UL_var1 - UL_var2; /*wrap may occur, like in C */
if (UL_var1 >= UL_var2)
{
*sgn = 0;
}
else
{
*sgn = 1; /* "negative" , wrapped output */
}
#if WMOPS
multiCounter[currCounter].L_sub++; /* now new counter added for UL_ */
#endif
return UL_var3;
}
/*****************************************************************************
*
* Function Name : Mpy_32_16_uu
*
* Purpose :
*
* Multiplies the 2 unsigned values UL_var1 and uvar2
* with saturation control on 48-bit.( does not happen for unsigned)
* The operation is performed in fractional mode :
* - UL_var1 is supposed to be in Q32 format.
* - var2 is supposed to be in Q16 format.
* - The result is produced in Q48 format : UL_varout_h points to the
* 32 MSBits while varout_l points to the 16 LSBits.
*
* Complexity weight : 2
*
* Inputs :
*
* UL_var1 32 bit long unsigned integer (UWord32) whose value falls in
* the range : 0x0000 0000 <= L_var1 <= 0xffff ffff.
*
* var2 16 bit short unsigned integer (UWord16) whose value falls in
* the range : 0x0000 <= var2 <= 0x0000 ffff.
*
* Outputs :
*
* *UL_varout_h 32 bit long unsigned integer (UWord32) whose value falls in
* the range : 0x0000 0000 <= UL_varout_h <= 0xffff ffff.
*
* *varout_l 16 bit short unsigned integer (UWord16) whose value falls in
* the range : 0x0000 0000 <= varout_l <= 0x0000 ffff.
*
* Return Value :
*
* none
*
*****************************************************************************/
void Mpy_32_16_uu( UWord32 UL_var1, UWord16 uvar2, UWord32 *UL_varout_h, UWord16 *varout_l) {
UWord64 UL64_var1;
/* 4294967295 * 65535 < 281474976710655 */
/* (uint64(2)^16-1 )*(uint64(2)^32-1) < (uint64(2)^(16+32)-1) */
{
UL64_var1 = ( UWord64) UL_var1 * ( UWord64)uvar2 ;
*varout_l = ( UWord16)( UL64_var1 );
*UL_varout_h = (UWord32)(UL64_var1>>16);
}
#if (WMOPS)
multiCounter[currCounter].Mpy_32_16_ss++; /* now new counter added for UL_ */
#endif /* if WMOPS */
return;
}
/*****************************************************************************
*
* Function Name : Mpy_32_32_uu
*
* Purpose :
*
* Multiplies the 2 unsigned values UL_var1 and UL_var2
* with saturation control on 64-bit. (not needed for unsigned)
* The operation is performed in fractional mode :
* - UL_var1 and UL_var2 are supposed to be in Q32 format.
* - The result is produced in Q64 format : UL_varout_h points to the
* 32 MSBits while UL_varout_l points to the 32 LSBits.
*
* Complexity weight : 4
*
* Inputs :
*
* UL_var1 32 bit long unsigned integer (UWord32) whose value falls in the
* range : 0x0000 0000 <= L_var1 <= 0xffff ffff.
*
* UL_var2 32 bit long unsigned integer (UWord32) whose value falls in the
* range : 0x0000 0000 <= L_var2 <= 0xffff ffff.
*
* Outputs :
*
* *UL_varout_h 32 bit long signed integer (Word32) whose value falls in
* the range : 0x0000 0000 <= UL_varout_h <= 0xffff ffff.
*
* *UL_varout_l 32 bit short unsigned integer (UWord32) whose value falls in
* the range : 0x0000 0000 <= UL_varout_l <= 0xffff ffff.
*
*
* Return Value :
*
* none
*
*****************************************************************************/
void Mpy_32_32_uu( UWord32 UL_var1, UWord32 UL_var2, UWord32 *UL_varout_h, UWord32 *UL_varout_l)
{
UWord64 UL64_var1;
/* (uint64(2)^32-1 )*(uint64(2)^32-1) < (uint64(2)^(32+32)-1) */
{
UL64_var1 = ((UWord64) UL_var1)*((UWord64) UL_var2);
*UL_varout_h = (UWord32)(UL64_var1>>32);
*UL_varout_l = (UWord32)(UL64_var1);
}
#if (WMOPS)
multiCounter[currCounter].Mpy_32_32_ss++; /* now new counter added for UL_ */
#endif /* if WMOPS */
return;
}
/*****************************************************************************
*
* Function Name : UL_Mpy_32_32
*
* Purpose :
*
* Multiplies the 2 unsigned values UL_var1 and UL_var2
* and returns the lower 32 bits, without saturation control.
*
* - UL_var1 and UL_var2 are supposed to be in Q32 format.
* - The result is produced in Q64 format, (the 32 LSBits. )
*
* operates like a regular 32-by-32 bit unsigned int multiplication in ANSI-C.
* UWord32) = (unsigned int)*(unsigned int);
*
*
* Complexity weight : 2
*
* Inputs :
*
* UL_var1 32 bit long unsigned integer (UWord32) whose value falls in the
* range : 0x0000 0000 <= UL_var1 <= 0xffff ffff.
*
* UL_var2 32 bit long unsigned integer (UWord32) whose value falls in the
* range : 0x0000 0000 <= UL_var2 <= 0xffff ffff.
*
* Outputs :
*
* Return Value :
* *UL_varout_l 32 bit short unsigned integer (UWord32) whose value falls in
* the range : 0x0000 0000 <= UL_varout_l <= 0xffff ffff.
*
* none
*
*****************************************************************************/
UWord32 UL_Mpy_32_32( UWord32 UL_var1, UWord32 UL_var2)
{
UWord32 UL_varout_l;
#define MASK32 0xFFFFFFFFU
/* MASK32 may be needed in case Hardware is using larger than 32 bits for UWord32 type) */
UL_varout_l = (UL_var1&MASK32)*(UL_var2&MASK32);
UL_varout_l = (UL_varout_l&MASK32);
#undef MASK32
#if (WMOPS)
multiCounter[currCounter].Mpy_32_16_ss++; /* now new counters added for UL_ ops*/
#endif /* if WMOPS */
return UL_varout_l;
}
#ifdef STL_TYPECASTS
/* (Reuse of existing signed STL "L" operators) with
typecasting to make the resulting "UL" code a lot cleaner and more readable. */
UWord32 UL_lshl( UWord32 UL_var1, Word16 var2) {
return( (UWord32)L_lshl( (Word32) UL_var1, var2));
}
UWord32 UL_lshr( UWord32 UL_var1, Word16 var2) {
return( (UWord32)L_lshr( (Word32) UL_var1, var2) );
}
UWord32 UL_and(UWord32 UL_var1, UWord32 UL_var2 )
{
return (UWord32) L_and((Word32)UL_var1,(Word32) UL_var2);
}
UWord32 UL_or(UWord32 UL_var1, UWord32 UL_var2 )
{
return (UWord32) L_or((Word32)UL_var1,(Word32) UL_var2);
}
UWord32 UL_xor(UWord32 UL_var1, UWord32 UL_var2 )
{
return (UWord32) L_xor((Word32)UL_var1,(Word32) UL_var2);
}
UWord32 UL_deposit_h(UWord16 uvar1)
{
return (UWord32) L_deposit_h((Word32)uvar1);
}
UWord16 u_extract_h(UWord32 UL_var1)
{
return (UWord16) extract_h((Word32)UL_var1);
}
UWord16 u_extract_l(UWord32 UL_var1)
{
return (UWord32)extract_l((Word32)UL_var1);
}
/* enable convenient reuse of Non-saturating UL_subNs , UL_addNs while "D"iscarding the sgn/wrap output flags */
UWord32 UL_subNsD(UWord32 UL_var1, UWord32 UL_var2 )
{
UWord16 dummy_sign;
return UL_subNs(UL_var1,UL_var2,&dummy_sign );
}
UWord32 UL_addNsD(UWord32 UL_var1, UWord32 UL_var2 )
{
UWord16 dummy_wrap;
return UL_addNs(UL_var1,UL_var2,&dummy_wrap );
}
#endif
#endif /* ENHUL32 */
/* end of file */

View File

@ -0,0 +1,82 @@
/*
===========================================================================
File: ENHUL32.H v.0.5 - 19.Mar.2014
===========================================================================
============================================================================
*/
#ifndef _ENHUL32_H
#define _ENHUL32_H
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
#define ENHUL32 /* all the enhanced unsigned operators */
#define STL_TYPECASTS /* logical shift and bitwise manipulation functions */
/* algorithmically exact to existing signed L_lshr and L_lshr */
#include "stl.h"
#ifndef UWord64
#define UWord64 unsigned long long /* for local use inside UL_Mpy_32_* */
#endif
#if (WMOPS)
#include "count.h"
extern BASIC_OP multiCounter[MAXCOUNTERS]; /* existing signed counters are reused for unsigedn operators */
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Prototypes for enhanced unsigned 32 bit arithmetic operators
*
*****************************************************************************/
UWord32 UL_addNs(UWord32 a, UWord32 b, UWord16* wrap);
UWord32 UL_subNs(UWord32 a, UWord32 b, UWord16* sgn);
UWord32 UL_Mpy_32_32(UWord32 a, UWord32 b);
void Mpy_32_32_uu( UWord32 a, UWord32 b, UWord32 *c_h, UWord32 *c_l); /* does not saturate */
void Mpy_32_16_uu( UWord32 a, UWord16 b,UWord32 *c_h, UWord16 *c_l); /* does not saturate */
/* Other */
Word16 norm_ul (UWord32 UL_var1);
UWord32 UL_deposit_l(UWord16); /* deposit low without sign extension ) */
/*****************************************************************************
*
* Inline Functions
*
*****************************************************************************/
#ifdef STL_TYPECASTS
/* (Reuse of existing signed STL "L" operators) with
typecasting to make the resulting "UL" code a lot cleaner and more readable. */
UWord32 UL_lshl( UWord32 UL_var1, Word16 var2);
UWord32 UL_lshr( UWord32 UL_var1, Word16 var2);
UWord32 UL_and(UWord32 UL_var1, UWord32 UL_var2 );
UWord32 UL_or(UWord32 UL_var1, UWord32 UL_var2 );
UWord32 UL_xor(UWord32 UL_var1, UWord32 UL_var2 );
UWord32 UL_deposit_h(UWord16 uvar1);
UWord16 u_extract_h(UWord32 UL_var1);
UWord16 u_extract_l(UWord32 UL_var1);
/* enable convenient reuse of Non-saturating UL_subNs , UL_addNs
while "D"iscarding the sgn/wrap output flags */
UWord32 UL_subNsD(UWord32 UL_var1, UWord32 UL_var2 );
UWord32 UL_addNsD(UWord32 UL_var1, UWord32 UL_var2 );
#endif
#endif /*_ENHUL32_H*/
/* end of file */

88
src/libs/libevs/basic_op/move.h Executable file
View File

@ -0,0 +1,88 @@
/*
===========================================================================
File: MOVE.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
MOVE & MISC LEGACY OPERATORS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
============================================================================
*/
#ifndef _MOVE_H
#define _MOVE_H
#include "stl.h"
#if (WMOPS)
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
static __inline void move16( void) {
#if WMOPS
multiCounter[currCounter].move16++;
#endif /* if WMOPS */
}
static __inline void move32( void) {
#if WMOPS
multiCounter[currCounter].move32++;
#endif /* if WMOPS */
}
static __inline void test( void) {
#if WMOPS
multiCounter[currCounter].Test++;
#endif /* if WMOPS */
}
static __inline void logic16( void) {
#if WMOPS
multiCounter[currCounter].Logic16++;
#endif /* if WMOPS */
}
static __inline void logic32( void) {
#if WMOPS
multiCounter[currCounter].Logic32++;
#endif /* if WMOPS */
}
/*-------- legacy ----------*/
#define data_move() move16()
#define L_data_move() move32()
#define data_move_external() move16()
#define compare_zero() test()
/*-------- end legacy ----------*/
#endif /* _MOVE_H */
/* end of file */

77
src/libs/libevs/basic_op/stl.h Executable file
View File

@ -0,0 +1,77 @@
/*
===========================================================================
File: STL.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
MAIN HEADER FILE
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
31 Mar 15 v2.1E Clarified usage of operators needed for the EVS codec.
============================================================================
*/
#ifndef _STL_H
#define _STL_H
/* This is Defined right here, it should be put in an include file
* that is included from every file. So far, only "stl.h" fit this
* requirement as "options.h" and "options.h" are not included by
* all code files. Also, these definitions are not enclosed by
* #if DEBUG because in some files, "stl.h" is included before
* DEBUG had been defined. This would lead to these macros not
* being defined and the Stack Counting would be disabled for some
* files. The Stack Counting would still work but some functions
* would be missing from the tree. */
extern int check_stack(const char*, const char*);
#define STACK_DEPTH_FCT_CALL (BASOP_push_wmops(__FUNCTION__), check_stack( __FILE__, __FUNCTION__))
#define STACK_DEPTH_FCT_RETURN (BASOP_pop_wmops(), check_stack("-"__FILE__, __FUNCTION__))
#include <stdlib.h> /* for size_t */
extern void* check_alloc_in(const char*, const char *, size_t, size_t);
extern void check_alloc_out(void*);
extern void check_alloc_exit(void);
#define MALLOC_FCT_CALL(n1) check_alloc_in("m"__FILE__, __FUNCTION__, n1, 0)
#define CALLOC_FCT_CALL(n1, n2) check_alloc_in("c"__FILE__, __FUNCTION__, n1, n2)
#define FREE_FCT_CALL(ptr) check_alloc_out(ptr)
/* both ALLOW_40bits and ALLOW_ENH_UL32 shall be enabled for the EVS codec. */
#define ALLOW_40bits /* allow 32x16 and 32x32 multiplications */
#define ALLOW_ENH_UL32 /* allow enhanced unsigned 32bit operators */
#if (defined _MSC_VER || defined __GNUC__ )
#include "typedef.h"
#include "basop32.h"
#include "count.h"
#include "move.h"
#include "control.h"
#include "enh1632.h"
#include "oper_32b.h"
#include "math_op.h"
#include "log2.h"
#if defined (ALLOW_40bits)
#include "enh40.h"
#endif
#if defined (ALLOW_ENH_UL32)
#include "enhUL32.h"
#endif
#endif /* if (defined _MSC_VER || defined __CYGWIN__) */
#endif /* ifndef _STL_H */
/* end of file */

View File

@ -0,0 +1,107 @@
/*
===========================================================================
File: TYPEDEF.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
TYPE DEFINITION PROTOTYPES
History:
26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729
basic operator library (based on basic_op.h)
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
============================================================================
*/
/*_____________________
| |
| Basic types. |
|_____________________|
*/
#ifndef _TYPEDEF_H
#define _TYPEDEF_H "$Id $"
#define ORIGINAL_TYPEDEF_H /* Define to get "original" version *
* of typedef.h (this file). */
#undef ORIGINAL_TYPEDEF_H /* Undefine to get the "new" version *
* of typedef.h (see typedefs.h). */
#ifdef ORIGINAL_TYPEDEF_H
/*
* This is the original code from the file typedef.h
*/
#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
typedef signed char Word8;
typedef short Word16;
typedef long Word32;
typedef __int64 Word40;
typedef unsigned short UWord16;
typedef unsigned long UWord32;
typedef int Flag;
#elif defined(__CYGWIN__)
typedef signed char Word8;
typedef short Word16;
typedef long Word32;
typedef long long Word40;
typedef unsigned short UWord16;
typedef unsigned long UWord32;
typedef int Flag;
#elif defined(__sun)
typedef signed char Word8;
typedef short Word16;
typedef long Word32;
/*#error "The 40-bit operations have not been tested on __sun : need to define Word40"*/
typedef long long Word40;
typedef unsigned short UWord16;
typedef unsigned long UWord32;
typedef int Flag;
#elif defined(__unix__) || defined(__unix)
typedef signed char Word8;
typedef short Word16;
typedef int Word32;
/*#error "The 40-bit operations have not been tested on unix : need to define Word40"*/
typedef long long Word40;
typedef unsigned short UWord16;
typedef unsigned int UWord32;
typedef int Flag;
#endif
#else /* ifdef ORIGINAL_TYPEDEF_H */ /* not original typedef.h */
/*
* Use (improved) type definition file typdefs.h and add a "Flag" type.
*/
#include "typedefs.h"
typedef int Flag;
#endif /* ifdef ORIGINAL_TYPEDEF_H */
#endif /* ifndef _TYPEDEF_H */
/* end of file */

View File

@ -0,0 +1,205 @@
/*
===========================================================================
File: TYPEDEFS.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
NEW TYPE DEFINITION PROTOTYPES
History:
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
Editor comment :
This file is not yet used or validated since
ORIGINAL_TYPEDEF_H compilation flag is defined in
typedef.h. This file is incorporated for future
reference / usage.
============================================================================
*/
/******************************************************************************
*
* File : typedefs.h
* Description : Definition of platform independent data
* types and constants
*
*
* The following platform independent data types and corresponding
* preprocessor (#define) constants are defined:
*
* defined type meaning corresponding constants
* ----------------------------------------------------------
* Char character (none)
* Bool boolean true, false
* Word8 8-bit signed minWord8, maxWord8
* UWord8 8-bit unsigned minUWord8, maxUWord8
* Word16 16-bit signed minWord16, maxWord16
* UWord16 16-bit unsigned minUWord16, maxUWord16
* Word32 32-bit signed minWord32, maxWord32
* UWord32 32-bit unsigned minUWord32, maxUWord32
* Float floating point minFloat, maxFloat
*
*
* The following compile switches are #defined:
*
* PLATFORM string indicating platform progam is compiled on
* possible values: "OSF", "PC", "SUN"
*
* OSF only defined if the current platform is an Alpha
* PC only defined if the current platform is a PC
* SUN only defined if the current platform is a Sun
*
* LSBFIRST is defined if the byte order on this platform is
* "least significant byte first" -> defined on DEC Alpha
* and PC, undefined on Sun
*
*****************************************************************************/
#ifndef _TYPEDEFS_H
#define _TYPEDEFS_H "$Id $"
/*****************************************************************************
* INCLUDE FILES
*****************************************************************************/
#include <float.h>
#include <limits.h>
/*****************************************************************************
* DEFINITION OF CONSTANTS
*****************************************************************************/
/*
********* define char type
*/
typedef char Char;
typedef unsigned short int UNS_Word16; /* 16 bit "register" (sw*) */
#ifdef UNS_Word16
#pragma message ("UNS_Word16 is defined but not officially part of STL2009@")
#endif
/*
********* define 8 bit signed/unsigned types & constants
*/
#if SCHAR_MAX == 127
typedef signed char Word8;
#define minWord8 SCHAR_MIN
#define maxWord8 SCHAR_MAX
typedef unsigned char UWord8;
#define minUWord8 0
#define maxUWord8 UCHAR_MAX
#else
#error cannot find 8-bit type
#endif
/*
********* define 16 bit signed/unsigned types & constants
*/
#if INT_MAX == 32767
typedef int Word16;
#define minWord16 INT_MIN
#define maxWord16 INT_MAX
typedef unsigned int UWord16;
#define minUWord16 0
#define maxUWord16 UINT_MAX
#elif SHRT_MAX == 32767
typedef short Word16;
#define minWord16 SHRT_MIN
#define maxWord16 SHRT_MAX
typedef unsigned short UWord16;
#define minUWord16 0
#define maxUWord16 USHRT_MAX
#else
#error cannot find 16-bit type
#endif
/* Definition of Word40 was missing 10/06/2013 */
#define Word40 long long
/*
********* define 32 bit signed/unsigned types & constants
*/
#if INT_MAX == 2147483647
typedef int Word32;
#define minWord32 INT_MIN
#define maxWord32 INT_MAX
typedef unsigned int UWord32;
#define minUWord32 0
#define maxUWord32 UINT_MAX
#elif LONG_MAX == 2147483647
typedef long Word32;
#define minWord32 LONG_MIN
#define maxWord32 LONG_MAX
typedef unsigned long UWord32;
#define minUWord32 0
#define maxUWord32 ULONG_MAX
#else
#error cannot find 32-bit type
#endif
/*
********* define floating point type & constants
*/
/* use "if 0" below if Float should be double;
use "if 1" below if Float should be float
*/
typedef double Float;
#define maxFloat DBL_MAX
#define minFloat DBL_MIN
/*
********* define complex type
*/
typedef struct {
Float r; /* real part */
Float i; /* imaginary part */
} CPX;
/*
********* define boolean type
*/
typedef int Bool;
#define false 0
#define true 1
/*
********* Check current platform
*/
#if defined(__MSDOS__)
#define PC
#define PLATFORM "PC"
#define LSBFIRST
#elif defined(__osf__)
#define OSF
#define PLATFORM "OSF"
#define LSBFIRST
#elif defined(__sun__) || defined(__sun)
#define SUN
#define PLATFORM "SUN"
#undef LSBFIRST
#elif defined(linux) && defined(i386)
#define PC
#define PLATFORM "PC"
#define LSBFIRST
#else
/*#error "can't determine architecture; adapt typedefs.h to your platform"*/
/* for MSVC 2008 10/06/2013 */
#define PC
#define PLATFORM "PC"
#define LSBFIRST
#endif
#endif /* ifndef _TYPEDEFS_H */
/* end of file */

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
src/libs/libevs/lib_com/ari.cpp Executable file
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);
}

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));
}
}

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();
}
}

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);
}

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

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

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;
}

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

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
src/libs/libevs/lib_com/cldfb.cpp Executable file

File diff suppressed because it is too large Load Diff

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
src/libs/libevs/lib_com/cnst_fx.h Executable file

File diff suppressed because it is too large Load Diff

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);
}
}
}
}

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;
}

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;
}

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;
}

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;
}

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 */

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*/
}

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;
}

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));
}
}
}

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 */
}

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;
}

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;
}

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;
}

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
src/libs/libevs/lib_com/fft.cpp Executable file

File diff suppressed because it is too large Load Diff

2832
src/libs/libevs/lib_com/fft_fx.cpp Executable file

File diff suppressed because it is too large Load Diff

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);
}
}

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;
}

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;
}

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;
}

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;
}

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
src/libs/libevs/lib_com/g192.cpp Executable file
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
src/libs/libevs/lib_com/g192.h Executable file
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 */

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 */
}

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;
}

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;
}

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;
}

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;
}

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;
}

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;
}

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
src/libs/libevs/lib_com/hp50.cpp Executable file
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;
}

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;
}

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();
}
}
}
}
}

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;
}

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;
}

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

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;
}

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

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;
}

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;
}

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);
}

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;
}

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
src/libs/libevs/lib_com/lerp.cpp Executable file
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 );
}
}

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;
}

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;
}

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;
}

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

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;
}

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