diff reid.c @ 5:59fc7fc126d0

mv utils.c reid.c In the original GSM 06.06 code drop, reid.c resides in the "utilities" collection (Dir_UTIL.zip), but there is also a copy of reid.c named utils.c in the "C" collection (Dir_C.zip), even though it is never compiled or linked as such. When I originally created the present Hg repository, I did not intend to include REID, only the main body of the codec - but I overlooked that utils.c copy, so it got imported. In the present time, however, it has become useful to have REID code in Hg for easier public study and discussion - so let's have it under its proper name.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 22 Jul 2024 18:43:12 +0000
parents utils.c@9008dbc8ca74
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reid.c	Mon Jul 22 18:43:12 2024 +0000
@@ -0,0 +1,1106 @@
+/*___________________________________________________________________________
+ |                                                                           |
+ |                                                                           |
+ |                 Residual Error Insertion Device                           |
+ |                                                                           |
+ |                                                                           |
+ |      File  :  REID.C                                                      |
+ |                                                                           |
+ |      Date  :  February 03, 1995                                           |
+ |                                                                           |
+ |      Version: 4.1                                                         |
+ |                                                                           |
+ |                                                                           |
+ |   Description:                                                            |
+ |   ------------                                                            |
+ |      This routine transforms the output file format of the GSM Half       |
+ |      Rate Encoder module consisting of:                                   |
+ |           * 18 speech parameters (see GSM TS 06.20)                       |
+ |           *  1 speech flag SP (see GSM TS 06.41)                          |
+ |           *  1 voice activity flag VAD (see GSM TS 06.42)                 |
+ |                                                                           |
+ |      to the input file format of the GSM Half Rate Decoder module         |
+ |      requiring:                                                           |
+ |           * 18 speech parameters (see GSM TS 06.20)                       |
+ |           *  1 channel condition flag BFI (see GSM TS 06.21, 05.05)       |
+ |           *  1 channel condition flag UFI (see GSM TS 06.21, 05.05)       |
+ |           *  1 SID flag (2 bits) (see GSM TS 06.41, 05.05)                |
+ |           *  1 time alignment flag TAF (see GSM TS 06.41)                 |
+ |                                                                           |
+ |      Between SID updates the speech parameters are replaced by random     |
+ |      values simulating an interrupted transmission on the air interface   |
+ |                                                                           |
+ |      The actual implementation only supports error free transmission (EP0)|
+ |                                                                           |
+ |      The shell for the future use of error patterns (residual error       |
+ |      pattern insertion) is already included.  If necessary, byte swapping |
+ |      is performed on the input speech parameters so that they are always  |
+ |      represented internally in PC byte order (assuming that the byte      |
+ |      order of the input file is compatible with the machine on which the  |
+ |      program is run).  However, byte swapping is not done on the flag     |
+ |      words (input: SP and VAD, output: BFI, UFI, SID, and TAF).  Thus,    |
+ |      the residual error pattern insertion code may be written to handle   |
+ |      the speech parameter words on a byte basis, but the flag words must  |
+ |      always be handled on a word basis.                                   |
+ |___________________________________________________________________________|
+*/
+/*___________________________________________________________________________
+ |                                                                           |
+ |      Creation: 19.12.94                                                   |
+ |                                                                           |
+ |  Changes:                                                                 |
+ |      22.12.94:  Removal of BCI flag, instead: determination of SID flag   |
+ |      12.01.95:  SID update period = 12 (instead of 24)                    |
+ |      13.01.95:  When in CNI mode, the parameters between SID updates are  |
+ |                 random values. This simulates the interrupted transmission|
+ |      03.02.95:  Longword main( Longword...) replaced by int main(int ...),|
+ |                 initial value of swTAFCnt set to 1                        |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |      Include-Files                                                        |
+ |___________________________________________________________________________|
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef VAX
+#   define OPEN_WI  "wb","mrs=512","rfm=fix","ctx=stm"
+#   define OPEN_RI  "rb","mrs=512","rfm=fix","ctx=stm"
+#   define OPEN_WB  "wb","mrs=512","rfm=fix","ctx=stm"
+#   define OPEN_RB  "rb","mrs=2","rfm=fix","ctx=stm"
+#   define OPEN_WT  "w","mrs=256","rat=cr","rfm=var"
+#   define OPEN_RT  "r","mrs=256","rat=cr","rfm=var"
+#else
+#   define OPEN_WB  "wb"
+#   define OPEN_RB  "rb"
+#   define OPEN_WI  "wb"
+#   define OPEN_RI  "rb"
+#   define OPEN_WT  "wt"
+#   define OPEN_RT  "rt"
+#endif
+
+#define LW_SIGN (long)0x80000000       /* sign bit */
+#define LW_MIN (long)0x80000000
+#define LW_MAX (long)0x7fffffff
+#define SW_MIN (short)0x8000           /* smallest Ram */
+#define SW_MAX (short)0x7fff           /* largest Ram */
+
+typedef char  Byte;
+typedef long int Longword;             /* 32 bit "accumulator" (L_*) */
+typedef short int Shortword;           /* 16 bit "register"  (sw*) */
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |      local Functions                                                      |
+ |___________________________________________________________________________|
+*/
+static Longword error_free( FILE *infile, FILE *outfile);
+static void SwapBytes( Shortword buffer[], Longword len );
+static Longword ByteOrder( void );
+static size_t ReadInputFile( Shortword buffer[], FILE *fp );
+static size_t WriteOutputFile( Shortword buffer[], FILE *fp );
+static Longword EncoderInterface( FILE *infile, Shortword swInPara[] );
+static Shortword swSidDetection(Shortword pswParameters[], 
+                                                  Shortword pswErrorFlag[]);
+static void RandomParameters(Shortword pswParameters[]);
+static Shortword getPnBits(Shortword iBits, Longword *pL_PNSeed);
+FILE *OpenBinfile( char *name, char *mode );
+Longword Strincmp( const char *s, const char *t, size_t max );
+Longword Stricmp( const char *s, const char *t );
+
+Longword L_shr(Longword L_var1, Shortword var2);   /* 2 ops */
+Longword L_shl(Longword L_var1, Shortword var2);   /* 2 ops */
+Shortword shr(Shortword var1, Shortword var2);     /* 1 ops */
+Shortword shl(Shortword var1, Shortword var2);     /* 1 ops */
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |      Subroutines                                                          |
+ |___________________________________________________________________________|
+*/
+static Longword error_free( FILE *infile, FILE *outfile)
+{
+
+#define SPEECH      1
+#define CNIFIRSTSID 2
+#define CNICONT     3
+#define VALIDSID    11
+#define GOODSPEECH  33
+
+    static Shortword swDecoMode = {SPEECH};
+    static Shortword swTAFCnt = {1};
+    Shortword swInPara[20], i, swFrameType;
+    Shortword swOutPara[22],pswErrorFlag[3];
+ 
+    if( EncoderInterface( infile, swInPara )) return( 1 );
+
+    /* Copy input parameters to output parameters (error free transmission) */
+    /* -------------------------------------------------------------------- */
+    for (i=0;i<18;i++)
+       swOutPara[i] = swInPara[i];
+
+    /* Set channel status flags (error free transmission) */
+    /* -------------------------------------------------- */
+    swOutPara[18] = 0;     /* BFI flag */
+    swOutPara[19] = 0;     /* UFI flag */
+
+    /* Evaluate SID flag */
+    /* ----------------- */
+    pswErrorFlag[0] = 0;   /* BFI flag */
+    pswErrorFlag[1] = 0;   /* UFI flag */
+    pswErrorFlag[2] = 0;   /* BCI flag */
+    swOutPara[20] = swSidDetection(swOutPara, pswErrorFlag);
+
+
+    /* Evaluate TAF flag */
+    /* ----------------- */
+    if (swTAFCnt == 0) swOutPara[21] = 1;
+    else               swOutPara[21] = 0;
+    swTAFCnt = (swTAFCnt + 1) % 12;
+
+   
+    /* Frame classification:                                                */
+    /* Since the transmission is error free, the received frames are either */
+    /* valid speech or valid SID frames                                     */
+    /* -------------------------------------------------------------------- */
+    if      ( swOutPara[20] == 2) swFrameType = VALIDSID;
+    else if ( swOutPara[20] == 0) swFrameType = GOODSPEECH;
+    else {
+            printf( "Error in SID detection\n" );
+            return( 1 );
+    }
+
+    /* Update of decoder state */
+    /* ----------------------- */
+    if (swDecoMode == SPEECH) {
+       if      (swFrameType == VALIDSID)   swDecoMode = CNIFIRSTSID;
+       else if (swFrameType == GOODSPEECH) swDecoMode = SPEECH;
+    }
+    else {  /* comfort noise insertion mode */
+       if      (swFrameType == VALIDSID)   swDecoMode = CNICONT;
+       else if (swFrameType == GOODSPEECH) swDecoMode = SPEECH;
+    }
+
+
+    /* Replace parameters by random data if in CNICONT-mode and TAF=0 */
+    /* -------------------------------------------------------------- */
+    if ((swDecoMode == CNICONT) && (swOutPara[21] == 0)){
+       RandomParameters(swOutPara);
+       /* Set flags such, that an "unusable frame" is produced */
+       swOutPara[18] = 1;     /* BFI flag */
+       swOutPara[19] = 1;     /* UFI flag */
+       swOutPara[20] = 0;     /* SID flag */
+    }    
+
+
+
+    if( outfile ) {
+        if( WriteOutputFile( swOutPara, outfile )) {
+            printf( "Error writing File\n" );
+            return( 1 );
+        }
+    }
+    return( 0 );
+}
+
+static Longword EncoderInterface( FILE *infile, Shortword swInPara[] )
+{
+    size_t i = 0;    
+
+    i = ReadInputFile( swInPara, infile );
+
+    return(( i == 0 ) ? 1 : 0 );
+}
+
+static size_t ReadInputFile( Shortword buffer[], FILE *fp )
+{
+    size_t i;
+
+    i = fread( buffer, sizeof( Shortword ), 20, fp );
+    SwapBytes( buffer, 18 );
+    return( i );
+}
+
+static size_t WriteOutputFile( Shortword buffer[], FILE *fp )
+{
+    size_t i;
+
+    SwapBytes( buffer, 18 );
+    i = fwrite( buffer, sizeof( Shortword ), 22, fp );
+    return( ( i == 22 ) ? 0 : 1 );
+}
+
+
+static void SwapBytes( Shortword buffer[], Longword len )
+{
+    Byte *pc, tmp;
+    Longword i;
+    
+    if( !ByteOrder())
+        return;
+    pc = (Byte *)buffer;
+    for( i = 0; i < len; i++ ) {
+        tmp   = pc[0];
+        pc[0] = pc[1];
+        pc[1] = tmp;
+        pc += 2;
+    }
+}
+
+static Longword ByteOrder( void )
+{
+    Shortword si;
+    Byte *pc;
+
+    si = 0x1234;
+    pc = (Byte *)&si;
+    if (pc[1] == 0x12 && pc[0] == 0x34 )
+            return( 0 );
+    if (pc[0] == 0x12 && pc[1] == 0x34 )
+            return( 1 );
+    printf( "Error in ByteOrder: %X, %X\n", (int)pc[0], (int)pc[1] );
+    exit( 1 );
+    return( 2 );
+}
+
+FILE *OpenBinfile( char *name, char *mode )
+{
+    FILE *fp;
+
+    if( toupper( *mode ) == 'W' ) { /* Write access */
+        if(( fp = fopen( name, OPEN_WB )) == NULL ) { 
+            printf( "Can't open output file '%s'\n", name );
+            exit( 1 );
+        }
+    } else { /* Read access */
+        if(( fp = fopen( name, OPEN_RB )) == NULL ) { 
+            printf( "Can't open file '%s'\n", name );
+            exit( 1 );
+        } 
+    }
+    return( fp );
+}
+
+Longword Strincmp( const char *s, const char *t, size_t max )
+{
+    for( ; max > 1; ++s, ++t, --max ) {
+        if( toupper( *s ) != toupper( *t ))
+            break;
+        if( *s == '\0' )
+            return( 0 );
+    }
+    return( toupper( *s ) - toupper( *t ));
+}
+
+Longword Stricmp( const char *s, const char *t )
+{
+    for(; toupper( *s ) == toupper( *t ); ++s, ++t ) {
+        if( *s == '\0' )
+            return( 0 );
+    }
+    return( toupper( *s ) - toupper( *t ));
+}
+
+/*************************************************************************
+ *
+ *   FUNCTION NAME: getPnBits
+ *
+ *   PURPOSE:
+ *     
+ *     Generate iBits pseudo-random bits using *pL_PNSeed as the
+ *     pn-generators seed.
+ *
+ *   INPUTS:
+ *
+ *     iBits - integer indicating how many random bits to return.
+ *     range [0,15], 0 yields 1 bit output
+ *     
+ *     *pL_PNSeed - 32 bit seed (changed by function)
+ *     
+ *   OUTPUTS:
+ *     
+ *     *pL_PNSeed - 32 bit seed, modified.
+ *     
+ *   RETURN VALUE:
+ *     
+ *    random bits in iBits LSB's.  
+ *     
+ *     
+ *   IMPLEMENTATION:
+ *     
+ *    implementation of x**31 + x**3 + 1 == PN_XOR_REG | PN_XOR_ADD a
+ *    PN sequence generator using Longwords generating a 2**31 -1
+ *    length pn-sequence.
+ *
+ *************************************************************************/
+
+static Shortword getPnBits(Shortword iBits, Longword *pL_PNSeed){
+
+#define PN_XOR_REG (Longword)0x00000005L
+#define PN_XOR_ADD (Longword)0x40000000L
+
+  Shortword swPnBits=0;
+  Longword L_Taps,L_FeedBack;
+  Shortword i;
+
+  for (i=0; i < iBits; i++){
+    
+    /* update the state */                     
+    /********************/
+    
+    L_Taps = *pL_PNSeed & PN_XOR_REG;  
+    L_FeedBack = L_Taps; /* Xor tap bits to yield feedback bit */
+    L_Taps = L_shr(L_Taps,1);
+
+    while(L_Taps){
+      L_FeedBack = L_FeedBack ^ L_Taps;
+      L_Taps = L_shr(L_Taps,1);
+    }
+
+    /* LSB of L_FeedBack is next MSB of PN register */
+
+    *pL_PNSeed = L_shr(*pL_PNSeed,1);
+    if (L_FeedBack & 1)
+       *pL_PNSeed = *pL_PNSeed | PN_XOR_ADD;
+    
+    /* State update complete.  
+       Get the output bit from the state, add/or it into output */
+
+    swPnBits = shl(swPnBits,1);
+    swPnBits = swPnBits | (*pL_PNSeed & 1);
+    
+  }
+  return(swPnBits);
+}
+
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME: L_shl
+ *
+ *   PURPOSE:
+ *
+ *     Arithmetic shift left (or right).
+ *     Arithmetically shift the input left by var2.   If var2 is
+ *     negative then an arithmetic shift right (L_shr) of L_var1 by
+ *     -var2 is performed.
+ *
+ *   INPUTS:
+ *
+ *     var2
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *     L_var1
+ *                     32 bit long signed integer (Longword) whose value
+ *                     falls in the range
+ *                     0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *   OUTPUTS:
+ *
+ *     none
+ *
+ *   RETURN VALUE:
+ *
+ *     L_Out
+ *                     32 bit long signed integer (Longword) whose value
+ *                     falls in the range
+ *                     0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ *
+ *   IMPLEMENTATION:
+ *
+ *     Arithmetically shift the 32 bit input left by var2.  This
+ *     operation maintains the sign of the input number. If var2 is
+ *     negative then an arithmetic shift right (L_shr) of L_var1 by
+ *     -var2 is performed.  See description of L_shr for details.
+ *
+ *     Equivalent to the Full-Rate GSM ">> n" operation.  Note that
+ *     ANSI-C does not guarantee operation of the C ">>" or "<<"
+ *     operator for negative numbers.
+ *
+ *   KEYWORDS: shift, arithmetic shift left,
+ *
+ *************************************************************************/
+
+Longword L_shl(Longword L_var1, Shortword var2)
+{
+
+  Longword L_Mask,
+         L_Out;
+  int    i,
+         iOverflow = 0;
+
+  if (var2 == 0 || L_var1 == 0)
+  {
+    L_Out = L_var1;
+  }
+  else if (var2 < 0)
+  {
+    if (var2 <= -31)
+    {
+      if (L_var1 > 0)
+        L_Out = 0;
+      else
+        L_Out = 0xffffffffL;
+    }
+    else
+      L_Out = L_shr(L_var1, -var2);
+  }
+  else
+  {
+
+    if (var2 >= 31)
+      iOverflow = 1;
+
+    else
+    {
+
+      if (L_var1 < 0)
+        L_Mask = LW_SIGN;              /* sign bit mask */
+      else
+        L_Mask = 0x0;
+      L_Out = L_var1;
+      for (i = 0; i < var2 && !iOverflow; i++)
+      {
+        /* check the sign bit */
+        L_Out = (L_Out & 0x7fffffffL) << 1;
+        if ((L_Mask ^ L_Out) & LW_SIGN)
+          iOverflow = 1;
+      }
+    }
+
+    if (iOverflow)
+    {
+      /* saturate */
+      if (L_var1 > 0)
+        L_Out = LW_MAX;
+      else
+        L_Out = LW_MIN;
+    }
+  }
+
+  return (L_Out);
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME: L_shr
+ *
+ *   PURPOSE:
+ *
+ *     Arithmetic shift right (or left).
+ *     Arithmetically shift the input right by var2.   If var2 is
+ *     negative then an arithmetic shift left (shl) of var1 by
+ *     -var2 is performed.
+ *
+ *   INPUTS:
+ *
+ *     var2
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *     L_var1
+ *                     32 bit long signed integer (Longword) whose value
+ *                     falls in the range
+ *                     0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *   OUTPUTS:
+ *
+ *     none
+ *
+ *   RETURN VALUE:
+ *
+ *     L_Out
+ *                     32 bit long signed integer (Longword) whose value
+ *                     falls in the range
+ *                     0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ *
+ *   IMPLEMENTATION:
+ *
+ *     Arithmetically shift the input right by var2.  This
+ *     operation maintains the sign of the input number. If var2 is
+ *     negative then an arithmetic shift left (shl) of L_var1 by
+ *     -var2 is performed.  See description of L_shl for details.
+ *
+ *     The input is a 32 bit number, as is the output.
+ *
+ *     Equivalent to the Full-Rate GSM ">> n" operation.  Note that
+ *     ANSI-C does not guarantee operation of the C ">>" or "<<"
+ *     operator for negative numbers.
+ *
+ *   KEYWORDS: shift, arithmetic shift right,
+ *
+ *************************************************************************/
+
+Longword L_shr(Longword L_var1, Shortword var2)
+{
+
+  Longword L_Mask,
+         L_Out;
+
+  if (var2 == 0 || L_var1 == 0)
+  {
+    L_Out = L_var1;
+  }
+  else if (var2 < 0)
+  {
+    /* perform a left shift */
+    /*----------------------*/
+    if (var2 <= -31)
+    {
+      /* saturate */
+      if (L_var1 > 0)
+        L_Out = LW_MAX;
+      else
+        L_Out = LW_MIN;
+    }
+    else
+      L_Out = L_shl(L_var1, -var2);
+  }
+  else
+  {
+
+    if (var2 >= 31)
+    {
+      if (L_var1 > 0)
+        L_Out = 0;
+      else
+        L_Out = 0xffffffffL;
+    }
+    else
+    {
+      L_Mask = 0;
+
+      if (L_var1 < 0)
+      {
+        L_Mask = ~L_Mask << (32 - var2);
+      }
+
+      L_var1 >>= var2;
+      L_Out = L_Mask | L_var1;
+    }
+  }
+  return (L_Out);
+}
+
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME: shl
+ *
+ *   PURPOSE:
+ *
+ *     Arithmetically shift the input left by var2.
+ *
+ *
+ *   INPUTS:
+ *
+ *     var1
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *     var2
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ *   OUTPUTS:
+ *
+ *     none
+ *
+ *   RETURN VALUE:
+ *
+ *     swOut
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range
+ *                     0xffff 8000 <= swOut <= 0x0000 7fff.
+ *
+ *   IMPLEMENTATION:
+ *
+ *     If Arithmetically shift the input left by var2.  If var2 is
+ *     negative then an arithmetic shift right (shr) of var1 by
+ *     -var2 is performed.  See description of shr for details.
+ *     When an arithmetic shift left is performed the var2 LS bits
+ *     are zero filled.
+ *
+ *     The only exception is if the left shift causes an overflow
+ *     or underflow.  In this case the LS bits are not modified.
+ *     The number returned is 0x8000 in the case of an underflow or
+ *     0x7fff in the case of an overflow.
+ *
+ *     The shl is equivalent to the Full-Rate GSM "<< n" operation.
+ *     Note that ANSI-C does not guarantee operation of the C ">>"
+ *     or "<<" operator for negative numbers - it is not specified
+ *     whether this shift is an arithmetic or logical shift.
+ *
+ *   KEYWORDS: asl, arithmetic shift left, shift
+ *
+ *************************************************************************/
+
+Shortword shl(Shortword var1, Shortword var2)
+{
+  Shortword swOut;
+  Longword L_Out;
+
+  if (var2 == 0 || var1 == 0)
+  {
+    swOut = var1;
+  }
+  else if (var2 < 0)
+  {
+
+    /* perform a right shift */
+    /*-----------------------*/
+
+    if (var2 <= -15)
+    {
+      if (var1 < 0)
+        swOut = (Shortword) 0xffff;
+      else
+        swOut = 0x0;
+    }
+    else
+      swOut = shr(var1, -var2);
+
+  }
+  else
+  {
+    /* var2 > 0 */
+    if (var2 >= 15)
+    {
+      /* saturate */
+      if (var1 > 0)
+        swOut = SW_MAX;
+      else
+        swOut = SW_MIN;
+    }
+    else
+    {
+
+      L_Out = (Longword) var1 *(1 << var2);
+
+      swOut = (Shortword) L_Out;       /* copy low portion to swOut,
+                                        * overflow could have hpnd */
+      if (swOut != L_Out)
+      {
+        /* overflow  */
+        if (var1 > 0)
+          swOut = SW_MAX;              /* saturate */
+        else
+          swOut = SW_MIN;              /* saturate */
+      }
+    }
+  }
+  return (swOut);
+}
+
+/***************************************************************************
+ *
+ *   FUNCTION NAME: shr
+ *
+ *   PURPOSE:
+ *
+ *     Arithmetic shift right (or left).
+ *     Arithmetically shift the input right by var2.   If var2 is
+ *     negative then an arithmetic shift left (shl) of var1 by
+ *     -var2 is performed.
+ *
+ *   INPUTS:
+ *
+ *     var1
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *     var2
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ *   OUTPUTS:
+ *
+ *     none
+ *
+ *   RETURN VALUE:
+ *
+ *     swOut
+ *                     16 bit short signed integer (Shortword) whose value
+ *                     falls in the range
+ *                     0xffff 8000 <= swOut <= 0x0000 7fff.
+ *
+ *   IMPLEMENTATION:
+ *
+ *     Arithmetically shift the input right by var2.  This
+ *     operation maintains the sign of the input number. If var2 is
+ *     negative then an arithmetic shift left (shl) of var1 by
+ *     -var2 is performed.  See description of shl for details.
+ *
+ *     Equivalent to the Full-Rate GSM ">> n" operation.  Note that
+ *     ANSI-C does not guarantee operation of the C ">>" or "<<"
+ *     operator for negative numbers.
+ *
+ *   KEYWORDS: shift, arithmetic shift right,
+ *
+ *************************************************************************/
+
+Shortword shr(Shortword var1, Shortword var2)
+{
+
+  Shortword swMask,
+         swOut;
+
+  if (var2 == 0 || var1 == 0)
+    swOut = var1;
+
+  else if (var2 < 0)
+  {
+    /* perform an arithmetic left shift */
+    /*----------------------------------*/
+    if (var2 <= -15)
+    {
+      /* saturate */
+      if (var1 > 0)
+        swOut = SW_MAX;
+      else
+        swOut = SW_MIN;
+    }
+    else
+      swOut = shl(var1, -var2);
+  }
+
+  else
+  {
+
+    /* positive shift count */
+    /*----------------------*/
+
+    if (var2 >= 15)
+    {
+      if (var1 < 0)
+        swOut = (Shortword) 0xffff;
+      else
+        swOut = 0x0;
+    }
+    else
+    {
+      /* take care of sign extension */
+      /*-----------------------------*/
+
+      swMask = 0;
+      if (var1 < 0)
+      {
+        swMask = ~swMask << (16 - var2);
+      }
+
+      var1 >>= var2;
+      swOut = swMask | var1;
+
+    }
+  }
+  return (swOut);
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |     This subroutine calculates the 'SID flag'                             |
+ |                                                                           |
+ |     Input:     pswParameters[18]                                          |
+ |                           input parameters of the speech decoder          |
+ |                                                                           |
+ |                pswErrorFlag[3]                                            |
+ |                           error flags, generated by channel decoder       |
+ |                                                                           |
+ |     Return Value:                                                         |
+ |                0:         speech frame detected                           |
+ |                1:         most likely SID frame received                  |
+ |                2:         SID frame detected                              |
+ |                                                                           |
+ |___________________________________________________________________________|
+ |                                                                           |
+ |     History:                                                              |
+ |                                                                           |
+ |     12-Oct-1994: Bug removed: error corrected in case of a mode (unvoiced/|
+ |                  voiced) mismatch, if a SID frame was received as an      |
+ |                  unvoiced frame                                           |
+ |___________________________________________________________________________|
+*/
+
+static Shortword swSidDetection(Shortword pswParameters[],
+                                Shortword pswErrorFlag[])
+{
+  static Shortword ppswIBit[2][18] = {
+        5, 11,9,8, 1, 2, 7,7,5, 7,7,5, 7,7,5, 7,7,5,  /* unvoiced */
+        5, 11,9,8, 1, 2, 8,9,5, 4,9,5, 4,9,5, 4,9,5}; /* voiced */
+
+  static Shortword ppswCL1pCL2[2][18] = {
+                              0x0001, /* R0      */  /* unvoiced */
+                              0x00ef, /* LPC1    */
+                              0x003e, /* LPC2    */
+                              0x007f, /* LPC3    */
+                              0x0001, /* INT LPC */
+                              0x0003, /* Mode    */
+                              0x001f, /* Code1_1 */
+                              0x0072, /* Code2_1 */
+                              0x0012, /* GSP0_1  */
+                              0x003f, /* Code1_2 */
+                              0x007f, /* Code2_2 */
+                              0x0008, /* GSP0_2  */
+                              0x007f, /* Code1_3 */
+                              0x007f, /* Code2_3 */
+                              0x0008, /* GSP0_3  */
+                              0x007f, /* Code1_4 */
+                              0x007f, /* Code2_4 */
+                              0x000c, /* GSP0_4  */
+                              
+                              0x0000, /* R0      */  /* voiced */
+                              0x0000, /* LPC1    */
+                              0x0000, /* LPC2    */
+                              0x0000, /* LPC3    */
+                              0x0001, /* INT LPC */
+                              0x0003, /* Mode    */
+                              0x00ff, /* Lag_1   */
+                              0x01ff, /* Code_1  */
+                              0x001f, /* GSP0_1  */
+                              0x000f, /* Lag_2   */
+                              0x01ff, /* Code_2  */
+                              0x001f, /* GSP0_2  */
+                              0x000f, /* Lag_3   */
+                              0x01ff, /* Code_3  */
+                              0x001f, /* GSP0_3  */
+                              0x000f, /* Lag_4   */
+                              0x01ff, /* Code_4  */
+                              0x001f}; /* GSP0_4 */
+
+  static Shortword ppswCL2[2][18] = {
+                              0x0000, /* R0      */ /* unvoiced */
+                              0x0000, /* LPC1    */
+                              0x0000, /* LPC2    */
+                              0x0000, /* LPC3    */
+                              0x0000, /* INT LPC */
+                              0x0000, /* Mode    */ 
+                              0x0000, /* Code1_1 */
+                              0x0000, /* Code2_1 */
+                              0x0000, /* GSP0_1  */
+                              0x0000, /* Code1_2 */
+                              0x0000, /* Code2_2 */
+                              0x0000, /* GSP0_2  */
+                              0x0000, /* Code1_3 */
+                              0x0007, /* Code2_3 */  /* 3 bits */
+                              0x0000, /* GSP0_3  */
+                              0x007f, /* Code1_4 */  /* 7 bits */
+                              0x007f, /* Code2_4 */  /* 7 bits */
+                              0x0000, /* GSP0_4  */
+
+                              0x0000, /* R0      */  /* voiced */
+                              0x0000, /* LPC1    */
+                              0x0000, /* LPC2    */
+                              0x0000, /* LPC3    */
+                              0x0000, /* INT LPC */
+                              0x0000, /* Mode    */
+                              0x0000, /* Lag_1   */
+                              0x0000, /* Code_1  */
+                              0x0000, /* GSP0_1  */
+                              0x0000, /* Lag_2   */
+                              0x0000, /* Code_2  */
+                              0x0000, /* GSP0_2  */
+                              0x0000, /* Lag_3   */
+                              0x00ff, /* Code_3  */  /* 8 bits */
+                              0x0000, /* GSP0_3  */
+                              0x0000, /* Lag_4   */
+                              0x01ff, /* Code_4  */  /* 9 bits */
+                              0x0000}; /* GSP0_4 */
+
+  static int first = 1;
+
+  Shortword swMode, swBitMask;
+  Shortword swSidN1, swSidN2, swSidN1pN2;
+  Shortword swSid ;
+
+  short siI, siII;
+
+
+  if (first)
+  {
+    /* Force Sid codewords to be represented */
+    /* internally in PC byte order           */
+    /* ------------------------------------- */
+
+    SwapBytes(ppswCL1pCL2[0], 18);
+    SwapBytes(ppswCL1pCL2[1], 18);
+    SwapBytes(ppswCL2[0], 18);
+    SwapBytes(ppswCL2[1], 18);
+
+    first = 0;
+  }
+
+
+  /* count transmission errors within the SID codeword      */
+  /* count number of bits equal '0' within the SID codeword */
+  /* ------------------------------------------------------ */
+
+  if (pswParameters[5] == 0)
+    swMode = 0;
+  else 
+    swMode = 1;
+  
+
+  swSidN1pN2 = 0;         /* N1 + N2 */
+  swSidN2    = 0;
+  swSidN1    = 0;
+  
+  for (siI = 0; siI < 18; siI++) {
+      swBitMask = 0x0001;
+      SwapBytes(&swBitMask, 1);  /* force swBitMask to PC byte order */
+      for (siII = 0; siII < ppswIBit[swMode][siI]; siII++) {
+        if ( (pswParameters[siI] & swBitMask) == 0 ) {
+          if ( (ppswCL1pCL2[swMode][siI] & swBitMask) != 0 ) swSidN1pN2++;
+          if ( (ppswCL2[swMode][siI] & swBitMask)     != 0 ) swSidN2++;
+        }
+        SwapBytes(&swBitMask, 1);  /* return swBitMask to native byte order */
+        swBitMask = swBitMask << 1;
+        SwapBytes(&swBitMask, 1);  /* force swBitMask to PC byte order */
+      }
+  }
+
+  swSidN1 = swSidN1pN2 - swSidN2;
+
+
+  /* frame classification */
+  /* -------------------- */
+
+  if (pswErrorFlag[2]) {
+
+    if (swSidN1 < 3)
+       swSid = 2;
+    else if (swSidN1pN2 < 16)
+       swSid = 1;
+    else
+       swSid = 0;
+     
+    if ( (swSidN1pN2 >= 16) && (swSidN1pN2 <= 25) ) {
+      pswErrorFlag[0] = 1;     
+    }
+
+  }
+  else {
+
+    if (swSidN1 < 3)
+       swSid = 2;
+    else if (swSidN1pN2 < 11)
+       swSid = 1;
+    else
+       swSid = 0;
+
+  }
+
+
+  /* in case of a mode mismatch */
+  /*----------------------------*/
+  
+  if ( (swSid == 2) && (swMode == 0) ) swSid = 1;
+
+  return(swSid);
+
+}
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |     This subroutine sets the 18 speech parameters to random values        |
+ |                                                                           |
+ |     Input:     pswParameters[18]                                          |
+ |                           input parameters of the speech decoder          |
+ |                                                                           |
+ |___________________________________________________________________________|
+*/
+
+static void RandomParameters(Shortword pswParameters[])
+{
+  static Shortword ppswIBit[2][18] = {
+             5, 11,9,8, 1, 2, 7,7,5, 7,7,5, 7,7,5, 7,7,5,  /* unvoiced */
+             5, 11,9,8, 1, 2, 8,9,5, 4,9,5, 4,9,5, 4,9,5}; /* voiced */
+
+  static Longword L_PNSeed=(Longword)0x1091988L;
+  Shortword  i,ind;
+
+  /* Determine mode bit */
+  /* ------------------ */
+  pswParameters[5] = getPnBits(2, &L_PNSeed);
+
+  /* Switch bit allocation accordingly */
+  /* --------------------------------- */
+  ind = 0;
+  if (pswParameters[5] > 0) ind = 1;
+
+  for (i=0; i < 5; i++){
+     pswParameters[i] = getPnBits(ppswIBit[ind][i], &L_PNSeed);
+  }
+  for (i=6; i < 18; i++){
+     pswParameters[i] = getPnBits(ppswIBit[ind][i], &L_PNSeed);
+  }
+
+  /* force random parameters to PC byte order */
+  /* ---------------------------------------- */
+
+  SwapBytes(pswParameters, 18);  
+}
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |     Main - Program                                                        |
+ |                                                                           |
+ |___________________________________________________________________________|
+*/
+int main( int argc, char *argv[] )
+{
+    FILE *infile, *outfile;
+    Shortword errpat, i = 0;
+
+    if( argc < 4 || argc > 4 ) {
+        fprintf( stderr, "\tUsage: REID input output EPx \n" );
+        fprintf( stderr, "\tEPx: EP0\n" );
+        fprintf( stderr, "\t     EP1 (not implemented)\n" );
+        fprintf( stderr, "\t     EP2 (not implemented)\n" );
+        fprintf( stderr, "\t     EP3 (not implemented)\n" );
+        return( 1 );
+    }
+
+
+    if( !Strincmp( argv[3], "ep", 2 )) 
+        errpat  = atoi( &argv[3][2] );
+
+    printf( "  _____________________________________________\n" );
+    printf( " |                                             |\n" );
+    printf( " |       Residual Error Insertion Device       |\n" );
+    printf( " |                 for                         |\n" );
+    printf( " |       GSM Half-Rate Codec Simulation        |\n" );
+    printf( " |                                             |\n" );
+    printf( " |_____________________________________________|\n\n" );
+
+    printf( "    Input File       : %s\n", argv[1] );
+    printf( "    Output File      : %s\n", argv[2] );
+    if( errpat ){
+        printf( "    Error Pattern    : EP%d (not implemented)\n", errpat);
+        return (1);
+    }
+    else
+        printf( "    Error Pattern    : EP%d (error free)\n", errpat );
+    printf( "\n" );
+
+    infile  = OpenBinfile( argv[1], "r" );
+    outfile = OpenBinfile( argv[2], "w" );
+
+
+    if (errpat == 0) {
+       for (i=0;i<6000;i++)
+           if( error_free( infile, outfile)) break;
+    }
+    /*else
+       for (i=0;i<6000;i++)
+           if( residual_error_pattern( infile, outfile)) break;
+        EP1-3 not implemented */
+
+    fclose( infile );
+    fclose( outfile );
+
+    printf( " %d Frame%s processed      \n\n", i,( i != 1 ) ? "s" : "" ); 
+    return( 0 );
+}