FreeCalypso > hg > gsm-codec-lib
view libgsmefr/basic_op.h @ 581:e2d5cad04cbf
libgsmhr1 RxFE: store CN R0+LPC separately from speech
In the original GSM 06.06 code the ECU for speech mode is entirely
separate from the CN generator, maintaining separate state. (The
main intertie between them is the speech vs CN state variable,
distinguishing between speech and CN BFIs, in addition to the
CN-specific function of distinguishing between initial and update
SIDs.)
In the present RxFE implementation I initially thought that we could
use the same saved_frame buffer for both ECU and CN, overwriting
just the first 4 params (R0 and LPC) when a valid SID comes in.
However, I now realize it was a bad idea: the original code has a
corner case (long sequence of speech-mode BFIs to put the ECU in
state 6, then SID and CN-mode BFIs, then a good speech frame) that
would be broken by that buffer reuse approach. We could eliminate
this corner case by resetting the ECU state when passing through
a CN insertion period, but doing so would needlessly increase
the behavioral diffs between GSM 06.06 and our version.
Solution: use a separate CN-specific buffer for CN R0+LPC parameters,
and match the behavior of GSM 06.06 code in this regard.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Feb 2025 10:02:45 +0000 |
parents | 9b05bbc23b8a |
children |
line wrap: on
line source
/* * This version of basic_op.h for GSM-EFR codec has been created at * Themyscira Wireless with the aim of performance improvement. * The original version contained only function declarations, * resulting in a function call for every elementary operation; * the present version implements most of these operations as inline * functions. (Further update: for extra speed-up, some inline * function implementations have been lifted from PacketVideo AMR * version, aka libopencore-amrnb.) * * Elimination of Overflow flag: examination of EFR code reveals that * both Carry and Overflow flags are accessed outside of basicop2.c * only in g_pitch.c, as part of a code sequence that uses L_macNs. * Since the Overflow flag is not checked anywhere else, we can eliminate * its setting from all other elementary operation functions, saving * some cycles and code size. * * Non-portability: we assume real target machines, not hypothetical * ones. Specifically, we assume that >> does an arithmetic right shift * (sign bit fill). */ /* for the few functions that still use them */ extern __thread Flag Overflow; extern __thread Flag Carry; #define MAX_32 (Word32)0x7fffffff #define MIN_32 (Word32)0x80000000 #define MAX_16 (Word16)0x7fff #define MIN_16 (Word16)0x8000 /* likely and unlikely conditional paths */ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) /* Word16 operations */ /*___________________________________________________________________________ | | | Function Name : add | | | | Purpose : | | | | Performs the addition (var1+var2) with overflow control and saturation;| | the 16 bit result is set at +32767 when overflow occurs or at -32768 | | when underflow occurs. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 add (Word16 var1, Word16 var2) { Word32 L_sum; L_sum = (Word32) var1 + var2; if (unlikely(L_sum > MAX_16)) return MAX_16; else if (unlikely(L_sum < MIN_16)) return MIN_16; else return L_sum; } /*___________________________________________________________________________ | | | Function Name : sub | | | | Purpose : | | | | Performs the subtraction (var1+var2) with overflow control and satu- | | ration; the 16 bit result is set at +32767 when overflow occurs or at | | -32768 when underflow occurs. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 sub (Word16 var1, Word16 var2) { Word32 L_diff; L_diff = (Word32) var1 - var2; if (unlikely(L_diff > MAX_16)) return MAX_16; else if (unlikely(L_diff < MIN_16)) return MIN_16; else return L_diff; } /*___________________________________________________________________________ | | | Function Name : abs_s | | | | Purpose : | | | | Absolute value of var1; abs_s(-32768) = 32767. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 abs_s (Word16 var1) { Word16 y = var1 - (var1 < 0); y = y ^ (y >> 15); return (y); } /*___________________________________________________________________________ | | | Function Name : shl | | | | Purpose : | | | | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| | the var2 LSB of the result. If var2 is negative, arithmetically shift | | var1 right by -var2 with sign extension. Saturate the result in case of | | underflows or overflows. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 shl (Word16 var1, Word16 var2) { Word16 var_out; if (unlikely(var2 < 0)) { if (unlikely(var2 < -15)) var2 = -15; var2 = -var2; var_out = var1 >> var2; } else { if (unlikely(var2 > 15)) var2 = 15; var_out = var1 << var2; if (unlikely(var_out >> var2 != var1)) { var_out = (var1 >> 15) ^ MAX_16; } } return var_out; } /*___________________________________________________________________________ | | | Function Name : shr | | | | Purpose : | | | | Arithmetically shift the 16 bit input var1 right var2 positions with | | sign extension. If var2 is negative, arithmetically shift var1 left by | | -var2 with sign extension. Saturate the result in case of underflows or | | overflows. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 shr (Word16 var1, Word16 var2) { Word16 var_out; if (unlikely(var2 < 0)) { if (unlikely(var2 < -15)) var2 = -15; var2 = -var2; var_out = var1 << var2; if (unlikely(var_out >> var2 != var1)) { var_out = (var1 >> 15) ^ MAX_16; } } else { if (unlikely(var2 > 15)) var2 = 15; var_out = var1 >> var2; } return var_out; } /*___________________________________________________________________________ | | | Function Name : mult | | | | Purpose : | | | | Performs the multiplication of var1 by var2 and gives a 16 bit result | | which is scaled i.e.: | | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | | mult(-32768,-32768) = 32767. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 mult (Word16 var1, Word16 var2) { register Word32 product; product = ((Word32) var1 * var2) >> 15; /* Saturate result (if necessary). */ /* var1 * var2 >0x00007fff is the only case */ /* that saturation occurs. */ if (unlikely(product > 0x00007fff)) product = (Word32) MAX_16; /* Return the product as a 16 bit value by type casting Word32 to Word16 */ return ((Word16) product); } /*___________________________________________________________________________ | | | Function Name : negate | | | | Purpose : | | | | Negate var1 with saturation, saturate in the case where input is -32768:| | negate(var1) = sub(0,var1). | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 negate (Word16 var1) { Word16 var_out; var_out = (var1 == MIN_16) ? MAX_16 : -var1; return (var_out); } /*___________________________________________________________________________ | | | Function Name : extract_h | | | | Purpose : | | | | Return the 16 MSB of L_var1. | | | | Complexity weight : 1 | | | | Inputs : | | | | L_var1 | | 32 bit long signed integer (Word32 ) whose value falls in the | | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 extract_h (Word32 L_var1) { Word16 var_out; var_out = (Word16) (L_var1 >> 16); return (var_out); } /*___________________________________________________________________________ | | | Function Name : extract_l | | | | Purpose : | | | | Return the 16 LSB of L_var1. | | | | Complexity weight : 1 | | | | Inputs : | | | | L_var1 | | 32 bit long signed integer (Word32 ) whose value falls in the | | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 extract_l (Word32 L_var1) { Word16 var_out; var_out = (Word16) L_var1; return (var_out); } /*___________________________________________________________________________ | | | Function Name : round | | | | Purpose : | | | | Round the lower 16 bits of the 32 bit input number into the MS 16 bits | | with saturation. Shift the resulting bits right by 16 and return the 16 | | bit number: | | round(L_var1) = extract_h(L_add(L_var1,32768)) | | | | Complexity weight : 1 | | | | Inputs : | | | | L_var1 | | 32 bit long signed integer (Word32 ) whose value falls in the | | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 round (Word32 L_var1) { if (unlikely(L_var1 >= 0x7fff8000)) return MAX_16; else return (L_var1 + 0x8000) >> 16; } /* Word32 operations */ /*___________________________________________________________________________ | | | Function Name : L_add | | | | Purpose : | | | | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | | overflow control and saturation; the result is set at +2147483647 when | | overflow occurs or at -2147483648 when underflow occurs. | | | | Complexity weight : 2 | | | | Inputs : | | | | L_var1 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | L_var2 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_add (Word32 L_var1, Word32 L_var2) { Word32 L_var_out; L_var_out = L_var1 + L_var2; if (((L_var1 ^ L_var2) & MIN_32) == 0) { if ((L_var_out ^ L_var1) & MIN_32) { L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; } } return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_sub | | | | Purpose : | | | | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | | overflow control and saturation; the result is set at +2147483647 when | | overflow occurs or at -2147483648 when underflow occurs. | | | | Complexity weight : 2 | | | | Inputs : | | | | L_var1 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | L_var2 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_sub (Word32 L_var1, Word32 L_var2) { Word32 L_var_out; L_var_out = L_var1 - L_var2; if (((L_var1 ^ L_var2) & MIN_32) != 0) { if ((L_var_out ^ L_var1) & MIN_32) { L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; } } return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_mult | | | | Purpose : | | | | L_mult is the 32 bit result of the multiplication of var1 times var2 | | with one shift left i.e.: | | L_mult(var1,var2) = L_shl((var1 times var2),1) and | | L_mult(-32768,-32768) = 2147483647. | | | | Complexity weight : 1 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_mult (Word16 var1, Word16 var2) { register Word32 L_product; L_product = (Word32) var1 * var2; if (likely(L_product != (Word32) 0x40000000)) { L_product <<= 1; /* Multiply by 2 */ } else { Overflow = 1; L_product = MAX_32; } return (L_product); } /*___________________________________________________________________________ | | | Function Name : L_mac | | | | Purpose : | | | | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | | result to L_var3 with saturation, return a 32 bit result: | | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | | | | Complexity weight : 1 | | | | Inputs : | | | | L_var3 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) { Word32 L_var_out; Word32 L_product; L_product = L_mult (var1, var2); L_var_out = L_add (L_var3, L_product); return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_msu | | | | Purpose : | | | | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | | bit result to L_var3 with saturation, return a 32 bit result: | | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | | | | Complexity weight : 1 | | | | Inputs : | | | | L_var3 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) { Word32 L_var_out; Word32 L_product; L_product = L_mult (var1, var2); L_var_out = L_sub (L_var3, L_product); return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_negate | | | | Purpose : | | | | Negate the 32 bit variable L_var1 with saturation; saturate in the case | | where input is -2147483648 (0x8000 0000). | | | | Complexity weight : 2 | | | | Inputs : | | | | L_var1 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_negate (Word32 L_var1) { Word32 L_var_out; L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1; return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_shl | | | | Purpose : | | | | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | | fill the var2 LSB of the result. If var2 is negative, arithmetically | | shift L_var1 right by -var2 with sign extension. Saturate the result in | | case of underflows or overflows. | | | | Complexity weight : 2 | | | | Inputs : | | | | L_var1 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_shl (Word32 L_var1, Word16 var2) { Word32 L_var_out; if (unlikely(var2 < 0)) { if (unlikely(var2 < -31)) var2 = -31; var2 = -var2; L_var_out = L_var1 >> var2; } else { if (unlikely(var2 > 31)) var2 = 31; L_var_out = L_var1 << var2; if (unlikely(L_var_out >> var2 != L_var1)) L_var_out = (L_var1 >> 31) ^ MAX_32; } return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_shr | | | | Purpose : | | | | Arithmetically shift the 32 bit input L_var1 right var2 positions with | | sign extension. If var2 is negative, arithmetically shift L_var1 left | | by -var2 and zero fill the -var2 LSB of the result. Saturate the result | | in case of underflows or overflows. | | | | Complexity weight : 2 | | | | Inputs : | | | | L_var1 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_shr (Word32 L_var1, Word16 var2) { Word32 L_var_out; if (unlikely(var2 < 0)) { if (unlikely(var2 < -31)) var2 = -31; var2 = -var2; L_var_out = L_var1 << var2; if (unlikely(L_var_out >> var2 != L_var1)) L_var_out = (L_var1 >> 31) ^ MAX_32; } else { if (unlikely(var2 > 31)) var2 = 31; L_var_out = L_var1 >> var2; } return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_deposit_h | | | | Purpose : | | | | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The | | 16 LS bits of the output are zeroed. | | | | Complexity weight : 2 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= var_out <= 0x7fff 0000. | |___________________________________________________________________________| */ static inline Word32 L_deposit_h (Word16 var1) { Word32 L_var_out; L_var_out = (Word32) var1 << 16; return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_deposit_l | | | | Purpose : | | | | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | | 16 MS bits of the output are sign extended. | | | | Complexity weight : 2 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word32 L_deposit_l (Word16 var1) { Word32 L_var_out; L_var_out = (Word32) var1; return (L_var_out); } /*___________________________________________________________________________ | | | Function Name : L_abs | | | | Purpose : | | | | Absolute value of L_var1; Saturate in case where the input is | | -214783648 | | | | Complexity weight : 3 | | | | Inputs : | | | | L_var1 | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | L_var_out | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x0000 0000 <= var_out <= 0x7fff ffff. | |___________________________________________________________________________| */ static inline Word32 L_abs (Word32 L_var1) { Word32 L_var_out; if (L_var1 == MIN_32) { L_var_out = MAX_32; } else { if (L_var1 < 0) { L_var_out = -L_var1; } else { L_var_out = L_var1; } } return (L_var_out); } /* additional ops */ /*___________________________________________________________________________ | | | Function Name : mult_r | | | | Purpose : | | | | Same as mult with rounding, i.e.: | | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | | mult_r(-32768,-32768) = 32767. | | | | Complexity weight : 2 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | var2 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | |___________________________________________________________________________| */ static inline Word16 mult_r (Word16 var1, Word16 var2) { Word16 var_out; Word32 L_product_arr; L_product_arr = (Word32) var1 *(Word32) var2; /* product */ L_product_arr += (Word32) 0x00004000L; /* round */ L_product_arr &= (Word32) 0xffff8000L; L_product_arr >>= 15; /* shift */ if (unlikely(L_product_arr > MAX_16)) return MAX_16; else if (unlikely(L_product_arr < MIN_16)) return MIN_16; else return L_product_arr; } /*___________________________________________________________________________ | | | Function Name : norm_s | | | | Purpose : | | | | Produces the number of left shift needed to normalize the 16 bit varia- | | ble var1 for positive values on the interval with minimum of 16384 and | | maximum of 32767, and for negative values on the interval with minimum | | of -32768 and maximum of -16384; in order to normalize the result, the | | following operation must be done : | | norm_var1 = shl(var1,norm_s(var1)). | | | | Complexity weight : 15 | | | | Inputs : | | | | var1 | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0x0000 0000 <= var_out <= 0x0000 000f. | |___________________________________________________________________________| */ static inline Word16 norm_s (Word16 var1) { Word16 var_out; if (var1 == 0) { var_out = 0; } else { if (var1 == (Word16) 0xffff) { var_out = 15; } else { if (var1 < 0) { var1 = ~var1; } for (var_out = 0; var1 < 0x4000; var_out++) { var1 <<= 1; } } } return (var_out); } /*___________________________________________________________________________ | | | Function Name : norm_l | | | | Purpose : | | | | Produces the number of left shifts needed to normalize the 32 bit varia-| | ble L_var1 for positive values on the interval with minimum of | | 1073741824 and maximum of 2147483647, and for negative values on the in-| | terval with minimum of -2147483648 and maximum of -1073741824; in order | | to normalize the result, the following operation must be done : | | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | | | | Complexity weight : 30 | | | | Inputs : | | | | L_var1 | | 32 bit long signed integer (Word32) whose value falls in the | | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | | | | Outputs : | | | | none | | | | Return Value : | | | | var_out | | 16 bit short signed integer (Word16) whose value falls in the | | range : 0x0000 0000 <= var_out <= 0x0000 001f. | |___________________________________________________________________________| */ static inline Word16 norm_l (Word32 L_var1) { Word16 var_out; if (L_var1 == 0) { var_out = 0; } else { if (L_var1 == (Word32) 0xffffffffL) { var_out = 31; } else { if (L_var1 < 0) { L_var1 = ~L_var1; } for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) { L_var1 <<= 1; } } } return (var_out); } /* ETSI functions that aren't inlined */ Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without sat, 1 */ Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without sat, 1 */ Word32 L_add_c (Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */ Word32 L_sub_c (Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */ Word16 shr_r (Word16 var1, Word16 var2); /* Shift right with round, 2 */ Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with rounding,2 */ Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with rounding,2 */ Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with round, 3 */ Word32 L_sat (Word32 L_var1); /* Long saturation, 4 */ Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */