it appears a one-character typo in the cmake_minimum_required line prevents it from compiling under CMake 4.0. in order to fix that, I had to take this thing out of submodules... it is recommended to do this after you pull; git submodule deinit extern/libsndfile
334 lines
6.9 KiB
C
334 lines
6.9 KiB
C
/*
|
|
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
|
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
|
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "gsm610_priv.h"
|
|
|
|
/*
|
|
* 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
|
|
*/
|
|
|
|
/* 4.2.4 */
|
|
|
|
|
|
static void Autocorrelation (
|
|
int16_t * s, /* [0..159] IN/OUT */
|
|
int32_t * L_ACF) /* [0..8] OUT */
|
|
/*
|
|
* The goal is to compute the array L_ACF [k]. The signal s [i] must
|
|
* be scaled in order to avoid an overflow situation.
|
|
*/
|
|
{
|
|
register int k, i ;
|
|
|
|
int16_t temp, smax, scalauto ;
|
|
|
|
#ifdef USE_FLOAT_MUL
|
|
float float_s [160] ;
|
|
#endif
|
|
|
|
/* Dynamic scaling of the array s [0..159] */
|
|
|
|
/* Search for the maximum. */
|
|
smax = 0 ;
|
|
for (k = 0 ; k <= 159 ; k++)
|
|
{ temp = GSM_ABS (s [k]) ;
|
|
if (temp > smax) smax = temp ;
|
|
}
|
|
|
|
/* Computation of the scaling factor.
|
|
*/
|
|
if (smax == 0)
|
|
scalauto = 0 ;
|
|
else
|
|
{ assert (smax > 0) ;
|
|
scalauto = 4 - gsm_norm ((int32_t) smax << 16) ; /* sub (4,..) */
|
|
}
|
|
|
|
/* Scaling of the array s [0...159]
|
|
*/
|
|
|
|
if (scalauto > 0)
|
|
{
|
|
|
|
# ifdef USE_FLOAT_MUL
|
|
# define SCALE(n) \
|
|
case n: for (k = 0 ; k <= 159 ; k++) \
|
|
float_s [k] = (float) \
|
|
(s [k] = GSM_MULT_R (s [k], 16384 >> (n-1))) ;\
|
|
break ;
|
|
# else
|
|
# define SCALE(n) \
|
|
case n: for (k = 0 ; k <= 159 ; k++) \
|
|
s [k] = GSM_MULT_R (s [k], 16384 >> (n-1)) ;\
|
|
break ;
|
|
# endif /* USE_FLOAT_MUL */
|
|
|
|
switch (scalauto) {
|
|
SCALE (1)
|
|
SCALE (2)
|
|
SCALE (3)
|
|
SCALE (4)
|
|
}
|
|
# undef SCALE
|
|
}
|
|
# ifdef USE_FLOAT_MUL
|
|
else for (k = 0 ; k <= 159 ; k++) float_s [k] = (float) s [k] ;
|
|
# endif
|
|
|
|
/* Compute the L_ACF [..].
|
|
*/
|
|
{
|
|
# ifdef USE_FLOAT_MUL
|
|
register float *sp = float_s ;
|
|
register float sl = *sp ;
|
|
|
|
# define STEP(k) L_ACF [k] += (int32_t) (sl * sp [- (k)]) ;
|
|
# else
|
|
int16_t *sp = s ;
|
|
int16_t sl = *sp ;
|
|
|
|
# define STEP(k) L_ACF [k] += ((int32_t) sl * sp [- (k)]) ;
|
|
# endif
|
|
|
|
# define NEXTI sl = *++sp
|
|
|
|
|
|
for (k = 9 ; k-- ; L_ACF [k] = 0) ;
|
|
|
|
STEP (0) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ; STEP (3) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ; STEP (3) ; STEP (4) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ; STEP (3) ; STEP (4) ; STEP (5) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ; STEP (3) ; STEP (4) ; STEP (5) ; STEP (6) ;
|
|
NEXTI ;
|
|
STEP (0) ; STEP (1) ; STEP (2) ; STEP (3) ; STEP (4) ; STEP (5) ; STEP (6) ; STEP (7) ;
|
|
|
|
for (i = 8 ; i <= 159 ; i++)
|
|
{ NEXTI ;
|
|
|
|
STEP (0) ;
|
|
STEP (1) ; STEP (2) ; STEP (3) ; STEP (4) ;
|
|
STEP (5) ; STEP (6) ; STEP (7) ; STEP (8) ;
|
|
}
|
|
|
|
for (k = 9 ; k-- ; )
|
|
L_ACF [k] = SASL_L (L_ACF [k], 1) ;
|
|
|
|
}
|
|
/* Rescaling of the array s [0..159]
|
|
*/
|
|
if (scalauto > 0)
|
|
{ assert (scalauto <= 4) ;
|
|
for (k = 160 ; k-- ; s++)
|
|
*s = SASL_W (*s, scalauto) ;
|
|
}
|
|
}
|
|
|
|
#if defined (USE_FLOAT_MUL) && defined (FAST)
|
|
|
|
static void Fast_Autocorrelation (
|
|
int16_t * s, /* [0..159] IN/OUT */
|
|
int32_t * L_ACF) /* [0..8] OUT */
|
|
{
|
|
register int k, i ;
|
|
float f_L_ACF [9] ;
|
|
float scale ;
|
|
|
|
float s_f [160] ;
|
|
register float *sf = s_f ;
|
|
|
|
for (i = 0 ; i < 160 ; ++i) sf [i] = s [i] ;
|
|
for (k = 0 ; k <= 8 ; k++)
|
|
{ register float L_temp2 = 0 ;
|
|
register float *sfl = sf - k ;
|
|
for (i = k ; i < 160 ; ++i) L_temp2 += sf [i] * sfl [i] ;
|
|
f_L_ACF [k] = L_temp2 ;
|
|
}
|
|
scale = 2147483648.0f / f_L_ACF [0] ;
|
|
|
|
for (k = 0 ; k <= 8 ; k++)
|
|
L_ACF [k] = f_L_ACF [k] * scale ;
|
|
}
|
|
#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */
|
|
|
|
/* 4.2.5 */
|
|
|
|
static void Reflection_coefficients (
|
|
int32_t * L_ACF, /* 0...8 IN */
|
|
register int16_t * r /* 0...7 OUT */
|
|
)
|
|
{
|
|
register int i, m, n ;
|
|
register int16_t temp ;
|
|
int16_t ACF [9] ; /* 0..8 */
|
|
int16_t P [9] ; /* 0..8 */
|
|
int16_t K [9] ; /* 2..8 */
|
|
|
|
/* Schur recursion with 16 bits arithmetic.
|
|
*/
|
|
|
|
if (L_ACF [0] == 0)
|
|
{ memset (r, 0, 8 * sizeof (r [0])) ;
|
|
return ;
|
|
}
|
|
|
|
assert (L_ACF [0] != 0) ;
|
|
temp = gsm_norm (L_ACF [0]) ;
|
|
|
|
assert (temp >= 0 && temp < 32) ;
|
|
|
|
/* ? overflow ? */
|
|
for (i = 0 ; i <= 8 ; i++) ACF [i] = SASR_L (SASL_L (L_ACF [i], temp), 16) ;
|
|
|
|
/* Initialize array P [..] and K [..] for the recursion.
|
|
*/
|
|
|
|
for (i = 1 ; i <= 7 ; i++) K [i] = ACF [i] ;
|
|
for (i = 0 ; i <= 8 ; i++) P [i] = ACF [i] ;
|
|
|
|
/* Compute reflection coefficients
|
|
*/
|
|
for (n = 1 ; n <= 8 ; n++, r++)
|
|
{ temp = P [1] ;
|
|
temp = GSM_ABS (temp) ;
|
|
if (P [0] < temp)
|
|
{ for (i = n ; i <= 8 ; i++) *r++ = 0 ;
|
|
return ;
|
|
}
|
|
|
|
*r = gsm_div (temp, P [0]) ;
|
|
|
|
assert (*r >= 0) ;
|
|
if (P [1] > 0) *r = -*r ; /* r [n] = sub (0, r [n]) */
|
|
assert (*r != MIN_WORD) ;
|
|
if (n == 8) return ;
|
|
|
|
/* Schur recursion
|
|
*/
|
|
temp = GSM_MULT_R (P [1], *r) ;
|
|
P [0] = GSM_ADD (P [0], temp) ;
|
|
|
|
for (m = 1 ; m <= 8 - n ; m++)
|
|
{ temp = GSM_MULT_R (K [m], *r) ;
|
|
P [m] = GSM_ADD (P [m + 1], temp) ;
|
|
|
|
temp = GSM_MULT_R (P [m + 1], *r) ;
|
|
K [m] = GSM_ADD (K [m], temp) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 4.2.6 */
|
|
|
|
static void Transformation_to_Log_Area_Ratios (
|
|
register int16_t * r /* 0..7 IN/OUT */
|
|
)
|
|
/*
|
|
* The following scaling for r [..] and LAR [..] has been used:
|
|
*
|
|
* r [..] = integer (real_r [..]*32768.) ; -1 <= real_r < 1.
|
|
* LAR [..] = integer (real_LAR [..] * 16384) ;
|
|
* with -1.625 <= real_LAR <= 1.625
|
|
*/
|
|
{
|
|
register int16_t temp ;
|
|
register int i ;
|
|
|
|
|
|
/* Computation of the LAR [0..7] from the r [0..7]
|
|
*/
|
|
for (i = 1 ; i <= 8 ; i++, r++)
|
|
{ temp = *r ;
|
|
temp = GSM_ABS (temp) ;
|
|
assert (temp >= 0) ;
|
|
|
|
if (temp < 22118)
|
|
{ temp >>= 1 ;
|
|
}
|
|
else if (temp < 31130)
|
|
{ assert (temp >= 11059) ;
|
|
temp -= 11059 ;
|
|
}
|
|
else
|
|
{ assert (temp >= 26112) ;
|
|
temp -= 26112 ;
|
|
temp <<= 2 ;
|
|
}
|
|
|
|
*r = *r < 0 ? -temp : temp ;
|
|
assert (*r != MIN_WORD) ;
|
|
}
|
|
}
|
|
|
|
/* 4.2.7 */
|
|
|
|
static void Quantization_and_coding (
|
|
register int16_t * LAR /* [0..7] IN/OUT */
|
|
)
|
|
{
|
|
register int16_t temp ;
|
|
|
|
/* This procedure needs four tables ; the following equations
|
|
* give the optimum scaling for the constants:
|
|
*
|
|
* A [0..7] = integer (real_A [0..7] * 1024)
|
|
* B [0..7] = integer (real_B [0..7] * 512)
|
|
* MAC [0..7] = maximum of the LARc [0..7]
|
|
* MIC [0..7] = minimum of the LARc [0..7]
|
|
*/
|
|
|
|
# undef STEP
|
|
# define STEP(A, B, MAC, MIC) \
|
|
temp = GSM_MULT (A, *LAR) ; \
|
|
temp = GSM_ADD (temp, B) ; \
|
|
temp = GSM_ADD (temp, 256) ; \
|
|
temp = SASR_W (temp, 9) ; \
|
|
*LAR = temp > MAC ? MAC - MIC : (temp < MIC ? 0 : temp - MIC) ; \
|
|
LAR++ ;
|
|
|
|
STEP (20480, 0, 31, -32) ;
|
|
STEP (20480, 0, 31, -32) ;
|
|
STEP (20480, 2048, 15, -16) ;
|
|
STEP (20480, -2560, 15, -16) ;
|
|
|
|
STEP (13964, 94, 7, -8) ;
|
|
STEP (15360, -1792, 7, -8) ;
|
|
STEP (8534, -341, 3, -4) ;
|
|
STEP (9036, -1144, 3, -4) ;
|
|
|
|
# undef STEP
|
|
}
|
|
|
|
void Gsm_LPC_Analysis (
|
|
struct gsm_state *S,
|
|
int16_t * s, /* 0..159 signals IN/OUT */
|
|
int16_t *LARc) /* 0..7 LARc's OUT */
|
|
{
|
|
int32_t L_ACF [9] ;
|
|
|
|
#if defined (USE_FLOAT_MUL) && defined (FAST)
|
|
if (S->fast)
|
|
Fast_Autocorrelation (s, L_ACF) ;
|
|
else
|
|
#endif
|
|
Autocorrelation (s, L_ACF ) ;
|
|
Reflection_coefficients (L_ACF, LARc ) ;
|
|
Transformation_to_Log_Area_Ratios (LARc) ;
|
|
Quantization_and_coding (LARc) ;
|
|
}
|