461 lines
10 KiB
C
461 lines
10 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 <assert.h>
|
||
|
|
|
||
|
|
#include "gsm610_priv.h"
|
||
|
|
|
||
|
|
/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* 4.2.13 */
|
||
|
|
|
||
|
|
static void Weighting_filter (
|
||
|
|
register int16_t * e, /* signal [-5..0.39.44] IN */
|
||
|
|
int16_t * x /* signal [0..39] OUT */
|
||
|
|
)
|
||
|
|
/*
|
||
|
|
* The coefficients of the weighting filter are stored in a table
|
||
|
|
* (see table 4.4). The following scaling is used:
|
||
|
|
*
|
||
|
|
* H[0..10] = integer(real_H [0..10] * 8192) ;
|
||
|
|
*/
|
||
|
|
{
|
||
|
|
/* int16_t wt [50] ; */
|
||
|
|
|
||
|
|
register int32_t L_result ;
|
||
|
|
register int k /* , i */ ;
|
||
|
|
|
||
|
|
/* Initialization of a temporary working array wt[0...49]
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* for (k = 0 ; k <= 4 ; k++) wt[k] = 0 ;
|
||
|
|
* for (k = 5 ; k <= 44 ; k++) wt[k] = *e++;
|
||
|
|
* for (k = 45 ; k <= 49 ; k++) wt[k] = 0 ;
|
||
|
|
*
|
||
|
|
* (e[-5..-1] and e[40..44] are allocated by the caller,
|
||
|
|
* are initially zero and are not written anywhere.)
|
||
|
|
*/
|
||
|
|
e -= 5 ;
|
||
|
|
|
||
|
|
/* Compute the signal x[0..39]
|
||
|
|
*/
|
||
|
|
for (k = 0 ; k <= 39 ; k++)
|
||
|
|
{ L_result = 8192 >> 1 ;
|
||
|
|
|
||
|
|
/* for (i = 0 ; i <= 10 ; i++) {
|
||
|
|
* L_temp = GSM_L_MULT(wt[k+i], gsm_H[i]) ;
|
||
|
|
* L_result = GSM_L_ADD(L_result, L_temp) ;
|
||
|
|
* }
|
||
|
|
*/
|
||
|
|
|
||
|
|
#undef STEP
|
||
|
|
#define STEP(i, H) (e [k + i] * (int32_t) H)
|
||
|
|
|
||
|
|
/* Every one of these multiplications is done twice --
|
||
|
|
* but I don't see an elegant way to optimize this.
|
||
|
|
* Do you?
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef STUPID_COMPILER
|
||
|
|
L_result += STEP (0, -134) ;
|
||
|
|
L_result += STEP (1, -374) ;
|
||
|
|
/* + STEP (2, 0) */
|
||
|
|
L_result += STEP (3, 2054) ;
|
||
|
|
L_result += STEP (4, 5741) ;
|
||
|
|
L_result += STEP (5, 8192) ;
|
||
|
|
L_result += STEP (6, 5741) ;
|
||
|
|
L_result += STEP (7, 2054) ;
|
||
|
|
/* + STEP (8, 0) */
|
||
|
|
L_result += STEP (9, -374) ;
|
||
|
|
L_result += STEP (10, -134) ;
|
||
|
|
#else
|
||
|
|
L_result += STEP (0, -134)
|
||
|
|
+ STEP (1, -374)
|
||
|
|
/* + STEP (2, 0) */
|
||
|
|
+ STEP (3, 2054)
|
||
|
|
+ STEP (4, 5741)
|
||
|
|
+ STEP (5, 8192)
|
||
|
|
+ STEP (6, 5741)
|
||
|
|
+ STEP (7, 2054)
|
||
|
|
/* + STEP (8, 0) */
|
||
|
|
+ STEP (9, -374)
|
||
|
|
+ STEP (10, -134) ;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* L_result = GSM_L_ADD(L_result, L_result) ; (* scaling(x2) *)
|
||
|
|
* L_result = GSM_L_ADD(L_result, L_result) ; (* scaling(x4) *)
|
||
|
|
*
|
||
|
|
* x[k] = SASR(L_result, 16) ;
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* 2 adds vs. >>16 => 14, minus one shift to compensate for
|
||
|
|
* those we lost when replacing L_MULT by '*'.
|
||
|
|
*/
|
||
|
|
|
||
|
|
L_result = SASR_L (L_result, 13) ;
|
||
|
|
x [k] = (L_result < MIN_WORD ? MIN_WORD
|
||
|
|
: (L_result > MAX_WORD ? MAX_WORD : L_result)) ;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 4.2.14 */
|
||
|
|
|
||
|
|
static void RPE_grid_selection (
|
||
|
|
int16_t * x, /* [0..39] IN */
|
||
|
|
int16_t * xM, /* [0..12] OUT */
|
||
|
|
int16_t * Mc_out /* OUT */
|
||
|
|
)
|
||
|
|
/*
|
||
|
|
* The signal x[0..39] is used to select the RPE grid which is
|
||
|
|
* represented by Mc.
|
||
|
|
*/
|
||
|
|
{
|
||
|
|
register int i ;
|
||
|
|
register int32_t L_result, L_temp ;
|
||
|
|
int32_t EM ; /* xxx should be L_EM? */
|
||
|
|
int16_t Mc ;
|
||
|
|
|
||
|
|
int32_t L_common_0_3 ;
|
||
|
|
|
||
|
|
EM = 0 ;
|
||
|
|
Mc = 0 ;
|
||
|
|
|
||
|
|
/* for (m = 0 ; m <= 3 ; m++) {
|
||
|
|
* L_result = 0 ;
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* for (i = 0 ; i <= 12 ; i++) {
|
||
|
|
*
|
||
|
|
* temp1 = SASR_W (x[m + 3*i], 2) ;
|
||
|
|
*
|
||
|
|
* assert (temp1 != MIN_WORD) ;
|
||
|
|
*
|
||
|
|
* L_temp = GSM_L_MULT(temp1, temp1) ;
|
||
|
|
* L_result = GSM_L_ADD(L_temp, L_result) ;
|
||
|
|
* }
|
||
|
|
*
|
||
|
|
* if (L_result > EM) {
|
||
|
|
* Mc = m ;
|
||
|
|
* EM = L_result ;
|
||
|
|
* }
|
||
|
|
* }
|
||
|
|
*/
|
||
|
|
|
||
|
|
#undef STEP
|
||
|
|
#define STEP(m, i) L_temp = SASR_W (x [m + 3 * i], 2) ; \
|
||
|
|
L_result += L_temp * L_temp ;
|
||
|
|
|
||
|
|
/* common part of 0 and 3 */
|
||
|
|
|
||
|
|
L_result = 0 ;
|
||
|
|
STEP (0, 1) ; STEP (0, 2) ; STEP (0, 3) ; STEP (0, 4) ;
|
||
|
|
STEP (0, 5) ; STEP (0, 6) ; STEP (0, 7) ; STEP (0, 8) ;
|
||
|
|
STEP (0, 9) ; STEP (0, 10) ; STEP (0, 11) ; STEP (0, 12) ;
|
||
|
|
L_common_0_3 = L_result ;
|
||
|
|
|
||
|
|
/* i = 0 */
|
||
|
|
|
||
|
|
STEP (0, 0) ;
|
||
|
|
L_result <<= 1 ; /* implicit in L_MULT */
|
||
|
|
EM = L_result ;
|
||
|
|
|
||
|
|
/* i = 1 */
|
||
|
|
|
||
|
|
L_result = 0 ;
|
||
|
|
STEP (1, 0) ;
|
||
|
|
STEP (1, 1) ; STEP (1, 2) ; STEP (1, 3) ; STEP (1, 4) ;
|
||
|
|
STEP (1, 5) ; STEP (1, 6) ; STEP (1, 7) ; STEP (1, 8) ;
|
||
|
|
STEP (1, 9) ; STEP (1, 10) ; STEP (1, 11) ; STEP (1, 12) ;
|
||
|
|
L_result <<= 1 ;
|
||
|
|
if (L_result > EM)
|
||
|
|
{ Mc = 1 ;
|
||
|
|
EM = L_result ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* i = 2 */
|
||
|
|
|
||
|
|
L_result = 0 ;
|
||
|
|
STEP (2, 0) ;
|
||
|
|
STEP (2, 1) ; STEP (2, 2) ; STEP (2, 3) ; STEP (2, 4) ;
|
||
|
|
STEP (2, 5) ; STEP (2, 6) ; STEP (2, 7) ; STEP (2, 8) ;
|
||
|
|
STEP (2, 9) ; STEP (2, 10) ; STEP (2, 11) ; STEP (2, 12) ;
|
||
|
|
L_result <<= 1 ;
|
||
|
|
if (L_result > EM)
|
||
|
|
{ Mc = 2 ;
|
||
|
|
EM = L_result ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* i = 3 */
|
||
|
|
|
||
|
|
L_result = L_common_0_3 ;
|
||
|
|
STEP (3, 12) ;
|
||
|
|
L_result <<= 1 ;
|
||
|
|
if (L_result > EM)
|
||
|
|
{ Mc = 3 ;
|
||
|
|
EM = L_result ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Down-sampling by a factor 3 to get the selected xM [0..12]
|
||
|
|
* RPE sequence.
|
||
|
|
*/
|
||
|
|
for (i = 0 ; i <= 12 ; i ++) xM [i] = x [Mc + 3 * i] ;
|
||
|
|
*Mc_out = Mc ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 4.12.15 */
|
||
|
|
|
||
|
|
static void APCM_quantization_xmaxc_to_exp_mant (
|
||
|
|
int16_t xmaxc, /* IN */
|
||
|
|
int16_t * expon_out, /* OUT */
|
||
|
|
int16_t * mant_out) /* OUT */
|
||
|
|
{
|
||
|
|
int16_t expon, mant ;
|
||
|
|
|
||
|
|
/* Compute expononent and mantissa of the decoded version of xmaxc
|
||
|
|
*/
|
||
|
|
|
||
|
|
expon = 0 ;
|
||
|
|
if (xmaxc > 15) expon = SASR_W (xmaxc, 3) - 1 ;
|
||
|
|
mant = xmaxc - (expon << 3) ;
|
||
|
|
|
||
|
|
if (mant == 0)
|
||
|
|
{ expon = -4 ;
|
||
|
|
mant = 7 ;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{ while (mant <= 7)
|
||
|
|
{ mant = mant << 1 | 1 ;
|
||
|
|
expon-- ;
|
||
|
|
}
|
||
|
|
mant -= 8 ;
|
||
|
|
}
|
||
|
|
|
||
|
|
assert (expon >= -4 && expon <= 6) ;
|
||
|
|
assert (mant >= 0 && mant <= 7) ;
|
||
|
|
|
||
|
|
*expon_out = expon ;
|
||
|
|
*mant_out = mant ;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void APCM_quantization (
|
||
|
|
int16_t * xM, /* [0..12] IN */
|
||
|
|
int16_t * xMc, /* [0..12] OUT */
|
||
|
|
int16_t * mant_out, /* OUT */
|
||
|
|
int16_t * expon_out, /* OUT */
|
||
|
|
int16_t * xmaxc_out /* OUT */
|
||
|
|
)
|
||
|
|
{
|
||
|
|
int i, itest ;
|
||
|
|
|
||
|
|
int16_t xmax, xmaxc, temp, temp1, temp2 ;
|
||
|
|
int16_t expon, mant ;
|
||
|
|
|
||
|
|
|
||
|
|
/* Find the maximum absolute value xmax of xM [0..12].
|
||
|
|
*/
|
||
|
|
|
||
|
|
xmax = 0 ;
|
||
|
|
for (i = 0 ; i <= 12 ; i++)
|
||
|
|
{ temp = xM [i] ;
|
||
|
|
temp = GSM_ABS (temp) ;
|
||
|
|
if (temp > xmax) xmax = temp ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Qantizing and coding of xmax to get xmaxc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
expon = 0 ;
|
||
|
|
temp = SASR_W (xmax, 9) ;
|
||
|
|
itest = 0 ;
|
||
|
|
|
||
|
|
for (i = 0 ; i <= 5 ; i++)
|
||
|
|
{ itest |= (temp <= 0) ;
|
||
|
|
temp = SASR_W (temp, 1) ;
|
||
|
|
|
||
|
|
assert (expon <= 5) ;
|
||
|
|
if (itest == 0) expon++ ; /* expon = add (expon, 1) */
|
||
|
|
}
|
||
|
|
|
||
|
|
assert (expon <= 6 && expon >= 0) ;
|
||
|
|
temp = expon + 5 ;
|
||
|
|
|
||
|
|
assert (temp <= 11 && temp >= 0) ;
|
||
|
|
xmaxc = gsm_add (SASR_W (xmax, temp), (int16_t) (expon << 3)) ;
|
||
|
|
|
||
|
|
/* Quantizing and coding of the xM [0..12] RPE sequence
|
||
|
|
* to get the xMc [0..12]
|
||
|
|
*/
|
||
|
|
|
||
|
|
APCM_quantization_xmaxc_to_exp_mant (xmaxc, &expon, &mant) ;
|
||
|
|
|
||
|
|
/* This computation uses the fact that the decoded version of xmaxc
|
||
|
|
* can be calculated by using the expononent and the mantissa part of
|
||
|
|
* xmaxc (logarithmic table).
|
||
|
|
* So, this method avoids any division and uses only a scaling
|
||
|
|
* of the RPE samples by a function of the expononent. A direct
|
||
|
|
* multiplication by the inverse of the mantissa (NRFAC[0..7]
|
||
|
|
* found in table 4.5) gives the 3 bit coded version xMc [0..12]
|
||
|
|
* of the RPE samples.
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
/* Direct computation of xMc [0..12] using table 4.5
|
||
|
|
*/
|
||
|
|
|
||
|
|
assert (expon <= 4096 && expon >= -4096) ;
|
||
|
|
assert (mant >= 0 && mant <= 7) ;
|
||
|
|
|
||
|
|
temp1 = 6 - expon ; /* normalization by the expononent */
|
||
|
|
temp2 = gsm_NRFAC [mant] ; /* inverse mantissa */
|
||
|
|
|
||
|
|
for (i = 0 ; i <= 12 ; i++)
|
||
|
|
{ assert (temp1 >= 0 && temp1 < 16) ;
|
||
|
|
|
||
|
|
temp = arith_shift_left (xM [i], temp1) ;
|
||
|
|
temp = GSM_MULT (temp, temp2) ;
|
||
|
|
temp = SASR_W (temp, 12) ;
|
||
|
|
xMc [i] = temp + 4 ; /* see note below */
|
||
|
|
}
|
||
|
|
|
||
|
|
/* NOTE: This equation is used to make all the xMc [i] positive.
|
||
|
|
*/
|
||
|
|
|
||
|
|
*mant_out = mant ;
|
||
|
|
*expon_out = expon ;
|
||
|
|
*xmaxc_out = xmaxc ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 4.2.16 */
|
||
|
|
|
||
|
|
static void APCM_inverse_quantization (
|
||
|
|
register int16_t * xMc, /* [0..12] IN */
|
||
|
|
int16_t mant,
|
||
|
|
int16_t expon,
|
||
|
|
register int16_t * xMp) /* [0..12] OUT */
|
||
|
|
/*
|
||
|
|
* This part is for decoding the RPE sequence of coded xMc [0..12]
|
||
|
|
* samples to obtain the xMp[0..12] array. Table 4.6 is used to get
|
||
|
|
* the mantissa of xmaxc (FAC[0..7]).
|
||
|
|
*/
|
||
|
|
{
|
||
|
|
int i ;
|
||
|
|
int16_t temp, temp1, temp2, temp3 ;
|
||
|
|
|
||
|
|
assert (mant >= 0 && mant <= 7) ;
|
||
|
|
|
||
|
|
temp1 = gsm_FAC [mant] ; /* see 4.2-15 for mant */
|
||
|
|
temp2 = gsm_sub (6, expon) ; /* see 4.2-15 for exp */
|
||
|
|
temp3 = gsm_asl (1, gsm_sub (temp2, 1)) ;
|
||
|
|
|
||
|
|
for (i = 13 ; i-- ;)
|
||
|
|
{ assert (*xMc <= 7 && *xMc >= 0) ; /* 3 bit unsigned */
|
||
|
|
|
||
|
|
/* temp = gsm_sub (*xMc++ << 1, 7) ; */
|
||
|
|
temp = (*xMc++ << 1) - 7 ; /* restore sign */
|
||
|
|
assert (temp <= 7 && temp >= -7) ; /* 4 bit signed */
|
||
|
|
|
||
|
|
temp = arith_shift_left (temp, 12) ; /* 16 bit signed */
|
||
|
|
temp = GSM_MULT_R (temp1, temp) ;
|
||
|
|
temp = GSM_ADD (temp, temp3) ;
|
||
|
|
*xMp++ = gsm_asr (temp, temp2) ;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 4.2.17 */
|
||
|
|
|
||
|
|
static void RPE_grid_positioning (
|
||
|
|
int16_t Mc, /* grid position IN */
|
||
|
|
register int16_t * xMp, /* [0..12] IN */
|
||
|
|
register int16_t * ep /* [0..39] OUT */
|
||
|
|
)
|
||
|
|
/*
|
||
|
|
* This procedure computes the reconstructed long term residual signal
|
||
|
|
* ep[0..39] for the LTP analysis filter. The inputs are the Mc
|
||
|
|
* which is the grid position selection and the xMp[0..12] decoded
|
||
|
|
* RPE samples which are upsampled by a factor of 3 by inserting zero
|
||
|
|
* values.
|
||
|
|
*/
|
||
|
|
{
|
||
|
|
int i = 13 ;
|
||
|
|
|
||
|
|
assert (0 <= Mc && Mc <= 3) ;
|
||
|
|
|
||
|
|
switch (Mc)
|
||
|
|
{ case 3: *ep++ = 0 ;
|
||
|
|
/* Falls through. */
|
||
|
|
case 2: do
|
||
|
|
{ *ep++ = 0 ;
|
||
|
|
/* Falls through. */
|
||
|
|
case 1: *ep++ = 0 ;
|
||
|
|
/* Falls through. */
|
||
|
|
case 0: *ep++ = *xMp++ ;
|
||
|
|
} while (--i) ;
|
||
|
|
}
|
||
|
|
while (++Mc < 4) *ep++ = 0 ;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 4.2.18 */
|
||
|
|
|
||
|
|
/* This procedure adds the reconstructed long term residual signal
|
||
|
|
* ep[0..39] to the estimated signal dpp[0..39] from the long term
|
||
|
|
* analysis filter to compute the reconstructed short term residual
|
||
|
|
* signal dp[-40..-1] ; also the reconstructed short term residual
|
||
|
|
* array dp[-120..-41] is updated.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#if 0 /* Has been inlined in code.c */
|
||
|
|
void Gsm_Update_of_reconstructed_short_time_residual_signal (
|
||
|
|
int16_t * dpp, /* [0...39] IN */
|
||
|
|
int16_t * ep, /* [0...39] IN */
|
||
|
|
int16_t * dp) /* [-120...-1] IN/OUT */
|
||
|
|
{
|
||
|
|
int k ;
|
||
|
|
|
||
|
|
for (k = 0 ; k <= 79 ; k++)
|
||
|
|
dp [-120 + k] = dp [-80 + k] ;
|
||
|
|
|
||
|
|
for (k = 0 ; k <= 39 ; k++)
|
||
|
|
dp [-40 + k] = gsm_add (ep [k], dpp [k]) ;
|
||
|
|
}
|
||
|
|
#endif /* Has been inlined in code.c */
|
||
|
|
|
||
|
|
void Gsm_RPE_Encoding (
|
||
|
|
int16_t * e, /* -5..-1][0..39][40..44 IN/OUT */
|
||
|
|
int16_t * xmaxc, /* OUT */
|
||
|
|
int16_t * Mc, /* OUT */
|
||
|
|
int16_t * xMc) /* [0..12] OUT */
|
||
|
|
{
|
||
|
|
int16_t x [40] ;
|
||
|
|
int16_t xM [13], xMp [13] ;
|
||
|
|
int16_t mant, expon ;
|
||
|
|
|
||
|
|
Weighting_filter (e, x) ;
|
||
|
|
RPE_grid_selection (x, xM, Mc) ;
|
||
|
|
|
||
|
|
APCM_quantization (xM, xMc, &mant, &expon, xmaxc) ;
|
||
|
|
APCM_inverse_quantization (xMc, mant, expon, xMp) ;
|
||
|
|
|
||
|
|
RPE_grid_positioning (*Mc, xMp, e) ;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void Gsm_RPE_Decoding (
|
||
|
|
int16_t xmaxcr,
|
||
|
|
int16_t Mcr,
|
||
|
|
int16_t * xMcr, /* [0..12], 3 bits IN */
|
||
|
|
int16_t * erp /* [0..39] OUT */
|
||
|
|
)
|
||
|
|
{
|
||
|
|
int16_t expon, mant ;
|
||
|
|
int16_t xMp [13] ;
|
||
|
|
|
||
|
|
APCM_quantization_xmaxc_to_exp_mant (xmaxcr, &expon, &mant) ;
|
||
|
|
APCM_inverse_quantization (xMcr, mant, expon, xMp) ;
|
||
|
|
RPE_grid_positioning (Mcr, xMp, erp) ;
|
||
|
|
}
|