FreeCalypso > hg > gsm-codec-lib
changeset 264:8b21a6b7a3bf
libgsmfr2: beginning to integrate TU-Berlin code guts
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 14 Apr 2024 00:06:50 +0000 |
parents | ffdcdb27d673 |
children | a7b593e68ac3 |
files | libgsmfr2/Makefile libgsmfr2/add.c libgsmfr2/ed_internal.h |
diffstat | 3 files changed, 411 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/libgsmfr2/Makefile Sat Apr 13 01:10:37 2024 +0000 +++ b/libgsmfr2/Makefile Sun Apr 14 00:06:50 2024 +0000 @@ -1,9 +1,9 @@ CC= gcc CFLAGS= -O2 -OBJS= comfort_noise.o ed_state.o pack_frame.o pack_frame2.o pp_bad.o \ +OBJS= add.o comfort_noise.o ed_state.o pack_frame.o pack_frame2.o pp_bad.o \ pp_good.o pp_state.o prng.o sidclass.o silence_frame.o unpack_frame.o \ unpack_frame2.o xmaxc_mean.o -HDRS= ed_state.h pp_internal.h pp_state.h tw_gsmfr.h typedef.h +HDRS= ed_internal.h ed_state.h pp_internal.h pp_state.h tw_gsmfr.h typedef.h LIB= libgsmfr2.a INSTALL_PREFIX= /usr/local
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmfr2/add.c Sun Apr 14 00:06:50 2024 +0000 @@ -0,0 +1,233 @@ +/* + * This C source file has been adapted from TU-Berlin libgsm source, + * original notice follows: + * + * 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 <stdint.h> +#include <assert.h> +#include <string.h> +#include "tw_gsmfr.h" +#include "typedef.h" +#include "ed_state.h" +#include "ed_internal.h" + +#define saturate(x) \ + ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) + +word gsm_add (word a, word b) +{ + longword sum = (longword)a + (longword)b; + return saturate(sum); +} + +word gsm_sub (word a, word b) +{ + longword diff = (longword)a - (longword)b; + return saturate(diff); +} + +word gsm_mult (word a, word b) +{ + if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; + else return SASR( (longword)a * (longword)b, 15 ); +} + +word gsm_mult_r (word a, word b) +{ + if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; + else { + longword prod = (longword)a * (longword)b + 16384; + prod >>= 15; + return prod & 0xFFFF; + } +} + +word gsm_abs (word a) +{ + return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; +} + +longword gsm_L_mult (word a, word b) +{ + assert( a != MIN_WORD || b != MIN_WORD ); + return ((longword)a * (longword)b) << 1; +} + +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; + } +} + +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; + } +} + +static unsigned char const 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 +}; + +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..) + */ +{ + assert(a != 0); + + if (a < 0) { + if (a <= -1073741824) return 0; + a = ~a; + } + + return a & 0xffff0000 + ? ( a & 0xff000000 + ? -1 + bitoff[ 0xFF & (a >> 24) ] + : 7 + bitoff[ 0xFF & (a >> 16) ] ) + : ( a & 0xff00 + ? 15 + bitoff[ 0xFF & (a >> 8) ] + : 23 + bitoff[ 0xFF & a ] ); +} + +longword gsm_L_asl (longword a, int n) +{ + if (n >= 32) return 0; + if (n <= -32) return -(a < 0); + if (n < 0) return gsm_L_asr(a, -n); + return a << n; +} + +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; +} + +longword gsm_L_asr (longword a, int n) +{ + if (n >= 32) return -(a < 0); + if (n <= -32) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(longword)( -(ulongword)a >> n ); +# endif +} + +word gsm_asr (word a, int n) +{ + if (n >= 16) return -(a < 0); + if (n <= -16) return 0; + if (n < 0) return a << -n; + +# ifdef SASR + return a >> n; +# else + if (a >= 0) return a >> n; + else return -(word)( -(uword)a >> n ); +# endif +} + +/* + * (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 + */ + +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); */ + + assert(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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmfr2/ed_internal.h Sun Apr 14 00:06:50 2024 +0000 @@ -0,0 +1,176 @@ +/* + * This header file has been adapted from inc/private.h + * in TU-Berlin libgsm source, original notice follows: + * + * 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. + */ + +#define SASR(x, by) ((x) >> (by)) + +/* + * Prototypes from add.c + */ +extern word gsm_mult (word a, word b); +extern longword gsm_L_mult (word a, word b); +extern word gsm_mult_r (word a, word b); + +extern word gsm_div (word num, word denum); + +extern word gsm_add ( word a, word b ); +extern longword gsm_L_add ( longword a, longword b ); + +extern word gsm_sub (word a, word b); +extern longword gsm_L_sub (longword a, longword b); + +extern word gsm_abs (word a); + +extern word gsm_norm ( longword a ); + +extern longword gsm_L_asl (longword a, int n); +extern word gsm_asl (word a, int n); + +extern longword gsm_L_asr (longword a, int n); +extern word gsm_asr (word a, int n); + +/* + * Inlined functions from add.h + */ + +/* + * #define GSM_MULT_R(a, b) (* word a, word b, !(a == b == MIN_WORD) *) \ + * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) + */ +#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) + +# define GSM_L_ADD(a, b) \ + ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ + : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ + >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ + : ((b) <= 0 ? (a) + (b) \ + : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ + ? MAX_LONGWORD : utmp)) + +/* + * # define GSM_ADD(a, b) \ + * ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \ + * ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) + */ +/* Nonportable, but faster: */ + +#define GSM_ADD(a, b) \ + ((ulongword)((ltmp = (longword)(a) + (longword)(b)) - MIN_WORD) > \ + MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp) + +# define GSM_SUB(a, b) \ + ((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \ + ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) + +# define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) + +/* Use these if necessary: + +# define GSM_MULT_R(a, b) gsm_mult_r(a, b) +# define GSM_MULT(a, b) gsm_mult(a, b) +# define GSM_L_MULT(a, b) gsm_L_mult(a, b) + +# define GSM_L_ADD(a, b) gsm_L_add(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) + +*/ + +/* + * More prototypes from implementations.. + */ + +void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */ + struct gsmfr_0610_state * S, + word * d, /* [0..39] residual signal IN */ + word * dp, /* [-120..-1] d' IN */ + word * e, /* [0..40] OUT */ + word * dpp, /* [0..40] OUT */ + word * Nc, /* correlation lag OUT */ + word * bc /* gain factor OUT */); + +void Gsm_LPC_Analysis ( + struct gsmfr_0610_state * S, + word * s, /* 0..159 signals IN/OUT */ + word * LARc); /* 0..7 LARc's OUT */ + +void Gsm_Preprocess ( + struct gsmfr_0610_state * S, + const word * s, word * so); + +void Gsm_Encoding ( + struct gsmfr_0610_state * S, + word * e, + word * ep, + word * xmaxc, + word * Mc, + word * xMc); + +void Gsm_Short_Term_Analysis_Filter ( + struct gsmfr_0610_state * S, + const word * LARc, /* coded log area ratio [0..7] IN */ + word * d /* st res. signal [0..159] IN/OUT */); + +void Gsm_Decoding ( + struct gsmfr_0610_state * S, + word xmaxcr, + word Mcr, + const word * xMcr, /* [0..12] IN */ + word * erp); /* [0..39] OUT */ + +void Gsm_Long_Term_Synthesis_Filtering ( + struct gsmfr_0610_state* S, + word Ncr, + word bcr, + word * erp, /* [0..39] IN */ + word * drp); /* [-120..-1] IN, [0..40] OUT */ + +void Gsm_RPE_Decoding ( + struct gsmfr_0610_state *S, + word xmaxcr, + word Mcr, + const word * xMcr, /* [0..12], 3 bits IN */ + word * erp); /* [0..39] OUT */ + +void Gsm_RPE_Encoding ( + struct gsmfr_0610_state * S, + word * e, /* -5..-1][0..39][40..44 IN/OUT */ + word * xmaxc, /* OUT */ + word * Mc, /* OUT */ + word * xMc); /* [0..12] OUT */ + +void Gsm_Short_Term_Synthesis_Filter ( + struct gsmfr_0610_state * S, + const word * LARcr, /* log area ratios [0..7] IN */ + word * drp, /* received d [0...39] IN */ + word * s); /* signal s [0..159] OUT */ + +void Gsm_Update_of_reconstructed_short_time_residual_signal ( + word * dpp, /* [0...39] IN */ + word * ep, /* [0...39] IN */ + word * dp); /* [-120...-1] IN/OUT */ + +/* + * Tables from table.c + */ + +extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; +extern word gsm_INVA[8]; +extern word gsm_DLB[4], gsm_QLB[4]; +extern word gsm_H[11]; +extern word gsm_NRFAC[8]; +extern word gsm_FAC[8];