furnace/extern/libsndfile-modified/src/GSM610/lpc.c
tildearrow 061991fe60 desubmodulize libsndfile - PLEASE READ
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
2025-04-02 15:09:53 -05:00

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