- reference source code for EVS codec
This commit is contained in:
parent
8c16c048dc
commit
94465da48e
|
|
@ -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)
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
@ -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];
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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*/
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue