Newsgroups: comp.speech
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!darwin.sura.net!metropolis!cfreese
From: cfreese@super.org (Craig F. Reese)
Subject: FAQ ulaw code is STILL incorrect....
Message-ID: <1994Dec27.173336.6283@super.org>
Sender: news@super.org (USENET News System)
Nntp-Posting-Host: hume
Organization: Supercomputing Research Center (Bowie, MD)
References: <comp-speech-faq/part1_787835355@rtfm.mit.edu> <comp-speech-faq/part2_787835355@rtfm.mit.edu>
Date: Tue, 27 Dec 1994 17:33:36 GMT
Lines: 156

In article <comp-speech-faq/part2_787835355@rtfm.mit.edu> andrewh@speech.su.oz.au (Andrew Hunt) writes:
>Archive-name: comp-speech-faq/part2
>Last-modified: 1994/12/19
>
>
>              COMP.SPEECH FAQ POSTING - PART 2/3
>
>   . . .
>
>     _________________________________________________________________
>   
>  Q2.7: HOW DO I CONVERT TO/FROM MU-LAW FORMAT?
>  
>
>   . . .
>
  
>   OR, here is some sample conversion code in C.
>   

  Bzzzt!  The code that followed was _still_ incorrect.  Some of the
  '>' '<' transpositions have been fixed.  Others have not.  The
  original (and correct) code from 1989 is appended to the end of this
  file.

  (Hopefully, our news system is now working and this will actually
  (get posted... *sigh*  I hate software....

  Craig

 
  Path: super!cfreese
  From: cfreese@super.ORG (Craig F. Reese)
  Newsgroups: comp.dsp
  Subject: SPARCStation audio conversion (ulaw <-> linear)
  Message-ID: <14899@super.ORG>
  Date: 29 Sep 89 23:23:49 GMT
  Sender: news@super.ORG
  Reply-To: cfreese@super.UUCP (Craig F. Reese)
  Distribution: na
  Organization: Supercomputing Research Center, Bowie, Md.
  Lines: 120
  
  TWIMC,
  
  Below are two routines I wrote for converting between ulaw and linear. 
  I use them with the SparcStation and they seem to work fine.
  I am pretty sure (99.9%) that they implement the standard as specified
  in the references. 
  
  Note that the standard deals with converting between 12 bit linear
  and 8 bit ulaw.  These routines assume 16 bit linear.  Thus, some
  bit shifting may be necessary.
  
  craig
  
  ------------------------------------------------------------------
  /**
   ** Signal conversion routines for use with the Sun4/60 audio chip
   **/
  
  /*
   * This routine converts from linear to ulaw
   * 29 September 1989
   *
   * Craig Reese: IDA/Supercomputing Research Center
   * Joe Campbell: Department of Defense
   *
   * References:
   * 1) CCITT Recommendation G.711  (very difficult to follow)
   * 2) "A New Digital Technique for Implementation of Any 
   *     Continuous PCM Companding Law," Villeret, Michel,
   *     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
   *     1973, pg. 11.12-11.17
   * 3) MIL-STD-188-113,"Interoperability and Performance Standards
   *     for Analog-to_Digital Conversion Techniques,"
   *     17 February 1987
   *
   * Input: Signed 16 bit linear sample
   * Output: 8 bit ulaw sample
   */
  
  #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
  #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
  #define CLIP 32635
  
  unsigned char
  linear2ulaw(sample)
  int sample;
  {
      static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
                                 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
                                 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
                                 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
                                 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
                                 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
                                 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
                                 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                                 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
      int sign, exponent, mantissa;
      unsigned char ulawbyte;
  
      /** get the sample into sign-magnitude **/
      sign = (sample >> 8) & 0x80;        /* set aside the sign */
      if (sign != 0) sample = -sample;    /* get magnitude */
      if (sample > CLIP) sample = CLIP;   /* clip the magnitude */
      /** convert from 16 bit linear to ulaw **/
      sample = sample + BIAS;
      exponent = exp_lut[(sample>>7) & 0xFF];
      mantissa = (sample >> (exponent+3)) & 0x0F;
      ulawbyte = ~(sign | (exponent << 4) | mantissa);
  #ifdef ZEROTRAP
      if (ulawbyte == 0 ) ulawbyte = 0x02;  /* optional CCITT trap */
  #endif
      /** return the result **/
      return(ulawbyte);
      }
  
  /*
   * This routine converts from ulaw to 16 bit linear
   * 29 September 1989
   *
   * Craig Reese: IDA/Supercomputing Research Center
   *
   * References:
   * 1) CCITT Recommendation G.711  (very difficult to follow)
   * 2) MIL-STD-188-113,"Interoperability and Performance Standards
   *     for Analog-to_Digital Conversion Techniques,"
   *     17 February 1987
   *
   * Input: 8 bit ulaw sample
   * Output: signed 16 bit linear sample
   */
  
  int
  ulaw2linear(ulawbyte)
  unsigned char ulawbyte;
  {
      static int exp_lut[8]={0,132,396,924,1980,4092,8316,16764};
      int sign, exponent, mantissa, sample;
  
      ulawbyte = ~ulawbyte;
      sign = (ulawbyte & 0x80);
      exponent = (ulawbyte >> 4) & 0x07;
      mantissa = ulawbyte & 0x0F;
      sample = exp_lut[exponent] + (mantissa << (exponent+3));
      if (sign != 0) sample = -sample;
      return(sample);
      }
