📄 gsm.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.
*
* 68K assembler routines by Curve Software, 6/95. To turn on 68K assembler,
* #define TARGET_68K.
*/
#include <stdio.h>
#define NDEBUG
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "gsm.private.h"
#include "gsm.h"
#ifdef PGP_MACINTOSH
#include "PGPfone.h"
#endif
/*
* #define BUG_FIX to correct bug in the C version of Short_term_synthesis_filtering().
*/
#define BUG_FIX
/*
* Set TARGET_X86 for 80x86 assembler routines.
*/
#ifdef PGP_WIN32
#define TARGET_X86
#endif
#define MIN_WORD ((-32767)-1)
#define MAX_WORD ( 32767)
#define MIN_LONGWORD ((-2147483647L)-1L)
#define MAX_LONGWORD ( 2147483647L)
#define SASR(x, by) ((x) >> (by))
#define GSM_MULT_R(a, b) /* word a, word b, !(a == b == MIN_WORD) */ \
(SASR( ((longword)(a) * (longword)(b) + 16384), 15 ))
# define GSM_MULT(a,b) /* word a, word b, !(a == b == MIN_WORD) */ \
(SASR( ((longword)(a) * (longword)(b)), 15 ))
# define GSM_L_MULT(a, b) /* word a, word b */ \
(((longword)(a) * (longword)(b)) << 1)
#ifdef PGP_WIN32
#define pgpAssert assert
#endif
#ifdef TARGET_X86
# include "asmcode.h"*/
# define GSM_L_ADD(a, b) Fgsm_L_add(a, b)
# define GSM_L_SUB(a, b) Fgsm_L_sub(a,b)
# define GSM_ADD(a, b) Fgsm_add(a, b)
# define GSM_SUB(a, b) Fgsm_sub(a, b)
# define GSM_ABS(a) Fgsm_abs(a)
# define GSM_ST_ANAL_FILT FShort_term_analysis_filtering
# define GSM_ST_SYNTH_FILT FShort_term_synthesis_filtering
# define GSM_LTP_LOOP FLTP_loop_internal
#else
# define GSM_L_ADD(a,b) gsm_l_add(a,b)
# define GSM_L_SUB(a,b) gsm_l_sub(a,b)
# define GSM_ADD(a,b) gsm_add(a,b)
# define GSM_SUB(a,b) gsm_sub(a,b)
# define GSM_ABS(a) gsm_abs(a)
# define GSM_ST_ANAL_FILT Short_term_analysis_filtering
# define GSM_ST_SYNTH_FILT Short_term_synthesis_filtering
# define GSM_LTP_LOOP LTP_loop_internal
#ifdef __MC68K__
asm word gsm_add(word warg1, word warg2)
{
fralloc+
move.w warg1,d0
add.w warg2,d0
bvc @end
bmi @pos
move.w #-0x8000,d0
bra @end
@pos:
move.w #0x7FFF, d0
@end:
frfree
rts
}
asm word gsm_sub(word warg1, word warg2)
{
fralloc+
move.w warg1,d0
sub.w warg2, d0
bvc @end
bmi @pos
move.w #-0x8000,d0
bra @end
@pos:
move.w #0x7FFF, d0
@end:
frfree
rts
}
asm longword gsm_l_add(longword warg1, longword warg2)
{
fralloc+
move.l warg1,d0
add.l warg2,d0
bvc @end
bmi @pos
move.l #0x8000000,d0
bra @end
@pos:
move.l #0x7FFFFFFF, d0
@end:
frfree
rts
}
asm longword gsm_l_sub(longword warg1, longword warg2)
{
fralloc+
move.l warg1,d0
sub.l warg2, d0
bvc @end
bmi @pos
move.l #0x80000000,d0
bra @end
@pos:
move.l #0x7FFFFFFF, d0
@end:
frfree
rts
}
#else /* __MC68K__ */
static word gsm_add(word warg1, word warg2) {
long x;
x = ((long) warg1) + ((long) warg2);
if (x<MIN_WORD) return MIN_WORD;
if (x>MAX_WORD) return MAX_WORD;
return x;
}
static word gsm_sub(word warg1, word warg2) {
long x;
x = ((long) warg1) - ((long) warg2);
if (x<MIN_WORD) return MIN_WORD;
if (x>MAX_WORD) return MAX_WORD;
return x;
}
static longword gsm_l_add(longword a, longword b)
{
if (a < 0) {
if (b >= 0) return a + b;
else {
ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1);
return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2;
}
}
else if (b <= 0) return a + b;
else {
ulongword A = (ulongword)a + (ulongword)b;
return A > MAX_LONGWORD ? MAX_LONGWORD : A;
}
}
static longword gsm_l_sub(longword a, longword b) {
if (a >= 0) {
if (b >= 0) return a - b;
else {
/* a>=0, b<0 */
ulongword A = (ulongword)a + -(b + 1);
return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1);
}
}
else if (b <= 0) return a - b;
else {
/* a<0, b>0 */
ulongword A = (ulongword)-(a + 1) + b;
return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1;
}
}
#endif /* __MC68K__ */
static word gsm_abs(word a)
{
return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
}
#endif /* TARGET_X86 */
static void Gsm_LPC_Analysis(
word * s, /* 0..159 signals IN/OUT */
word * LARc); /* 0..7 LARc's OUT */
static void Gsm_Short_Term_Analysis_Filter(
struct gsm_state * S,
word * LARc, /* coded log area ratio [0..7] IN */
word * s); /* signal [0..159] IN/OUT */
static void Gsm_Long_Term_Predictor(
struct gsm_state * S,
word * d, /* [0..39] residual signal IN */
word * dp, /* [-120..-1] d' IN */
word * e, /* [0..39] OUT */
word * dpp, /* [0..39] OUT */
word * Nc, /* correlation lag OUT */
word * bc); /* gain factor OUT */
static void Gsm_RPE_Encoding(
word * e, /* -5..-1][0..39][40..44 IN/OUT */
word * xmaxc, /* OUT */
word * Mc, /* OUT */
word * xMc); /* [0..12] OUT */
static void Gsm_RPE_Decoding(
word xmaxcr,
word Mcr,
word * xMcr, /* [0..12], 3 bits IN */
word * erp ); /* [0..39] OUT */
static void Gsm_Long_Term_Synthesis_Filtering(
struct gsm_state * S,
word Ncr,
word bcr,
register word * erp, /* [0..39] IN */
register word * drp /* [-120..-1] IN, [0..40] OUT */
);
static void Gsm_Short_Term_Synthesis_Filter(
struct gsm_state * S,
word * LARcr, /* received log area ratios [0..7] IN */
word * wt, /* received d [0..159] IN */
word * s /* signal s [0..159] OUT */
);
static void Quantization_and_coding(
register word * LAR /* [0..7] IN/OUT */
);
static unsigned char bitoff[ 256 ] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
short gsm_option( gsm r, short opt, short * val)
{
short result = -1;
switch (opt) {
case GSM_OPT_LTP_CUT:
#ifdef LTP_CUT
result = r->ltp_cut;
if (val) r->ltp_cut = *val;
#endif
break;
case GSM_OPT_VERBOSE:
#ifndef NDEBUG
result = r->verbose;
if (val) r->verbose = *val;
#endif
break;
case GSM_OPT_FAST:
#if defined(FAST) && defined(USE_FLOAT_MUL)
result = r->fast;
if (val) r->fast = !!*val;
#endif
break;
default:
break;
}
return result;
}
static word gsm_norm(longword a )
/*
* the number of left shifts needed to normalize the 32 bit
* variable L_var1 for positive values on the interval
*
* with minimum of
* minimum of 1073741824 (01000000000000000000000000000000) and
* maximum of 2147483647 (01111111111111111111111111111111)
*
*
* and for negative values on the interval with
* minimum of -2147483648 (-10000000000000000000000000000000) and
* maximum of -1073741824 ( -1000000000000000000000000000000).
*
* in order to normalize the result, the following
* operation must be done: L_norm_var1 = L_var1 << norm( L_var1 );
*
* (That's 'ffs', only from the left, not the right..)
*/
{
pgpAssert(a != 0);
if (a < 0) {
if (a <= -1073741824L) return 0;
a = ~a;
}
return a & 0xffff0000L
? ( a & 0xff000000L
? -1 + bitoff[ 0xFF & (a >> 24) ]
: 7 + bitoff[ 0xFF & (a >> 16) ] )
: ( a & 0xff00
? 15 + bitoff[ 0xFF & (a >> 8) ]
: 23 + bitoff[ 0xFF & a ] );
}
static word gsm_asr( word a, int n)
{
if (n >= 16) return -(a < 0);
if (n <= -16) return 0;
if (n < 0) return a << -n;
return a >> n;
}
static word gsm_asl(word a, int n)
{
if (n >= 16) return 0;
if (n <= -16) return -(a < 0);
if (n < 0) return gsm_asr(a, -n);
return a << n;
}
/*
* (From p. 46, end of section 4.2.5)
*
* NOTE: The following lines gives [sic] one correct implementation
* of the div(num, denum) arithmetic operation. Compute div
* which is the integer division of num by denum: with denum
* >= num > 0
*/
static word gsm_div(word num, word denum)
{
longword L_num = num;
longword L_denum = denum;
word div = 0;
int k = 15;
/* The parameter num sometimes becomes zero.
* Although this is explicitly guarded against in 4.2.5,
* we assume that the result should then be zero as well.
*/
/* assert(num != 0); */
pgpAssert(num >= 0 && denum >= num);
if (num == 0)
return 0;
while (k--) {
div <<= 1;
L_num <<= 1;
if (L_num >= L_denum) {
L_num -= L_denum;
div++;
}
}
return div;
}
/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP
* CODER AND DECODER
*
* (Most of them inlined, so watch out.)
*/
/* Table 4.3a Decision level of the LTP gain quantizer
*/
/* bc 0 1 2 3 */
word gsm_DLB[4] = { 6554, 16384, 26214, 32767 };
/* Table 4.3b Quantization levels of the LTP gain quantizer
*/
/* bc 0 1 2 3 */
static word gsm_QLB[4] = { 3277, 11469, 21299, 32767 };
/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax
*/
/* i 0 1 2 3 4 5 6 7 */
static word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 };
/* Table 4.6 Normalized direct mantissa used to compute xM/xmax
*/
/* i 0 1 2 3 4 5 6 7 */
static word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 };
/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION
*
* After A-law to linear conversion (or directly from the
* Ato D converter) the following scaling is assumed for
* input to the RPE-LTP algorithm:
*
* in: 0.1.....................12
* S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.*
*
* Where S is the sign bit, v a valid bit, and * a "don't care" bit.
* The original signal is called sop[..]
*
* out: 0.1................... 12
* S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0
*/
static void Gsm_Preprocess(
struct gsm_state * S,
word * s,
word * so ) /* [0..159] IN/OUT */
{
word z1 = S->z1;
longword L_z2 = S->L_z2;
word mp = S->mp;
word s1;
longword L_s2;
longword L_temp;
word msp, lsp;
word SO;
/* longword ltmp; /* for ADD */
/* ulongword utmp; /* for L_ADD */
register int k = 160;
while (k--) {
/* 4.2.1 Downscaling of the input signal
*/
SO = SASR( *s, 3 ) << 2;
s++;
pgpAssert (SO >= -0x4000); /* downscaled by */
pgpAssert (SO <= 0x3FFC); /* previous routine. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -