🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

2 total messages Started by Craig F. Reese Fri, 29 Sep 1989 23:23
SPARCStation audio conversion (ulaw <-> linear)
#334
Author: Craig F. Reese
Date: Fri, 29 Sep 1989 23:23
120 lines
4707 bytes
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);
    }

-----------------
Craig F. Reese                           Email: cfreese@super.org
Institute for Defense Analyses/
Supercomputing Research Center
17100 Science Dr.
Bowie, MD  20715-4300
Re: SPARCStation audio conversion (ulaw <-> linear)
#475
Author: Jef Poskanzer
Date: Mon, 23 Oct 1989 16:12
73 lines
3864 bytes
In the referenced message, cfreese@super.UUCP (Craig F. Reese) wrote:
}Below are two routines I wrote for converting between ulaw and linear. 
}I use them with the SparcStation and they seem to work fine.

Thanks, those will be very useful.

Since I haven't seen anyone else post it, appended is the obvious
table-lookup version of Craig's ulaw to linear converter.  I did
some timings on a SPARCstation.  In nanoseconds:

    counting subroutine call    not counting subroutine call
        old         new               old         new 

       1217         557               913         253

Also, the table in interesting in its own right, to get a feel for
just what ulaw does.  Corrections welcome, otherwise enjoy.
---
Jef

    Jef Poskanzer  pokey@well.sf.ca.us  {ucbvax, apple, hplabs}!well!pokey
               Specifications subject to change without notice.

/*
** This routine converts from ulaw to 16 bit linear, but faster.
**
** Jef Poskanzer
** 23 October 1989
**
** Input: 8 bit ulaw sample
** Output: signed 16 bit linear sample
*/

int
ulaw2linear(ulawbyte)
unsigned char ulawbyte;
{
    static int ulaw_table[] = {
	-32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, 
	-23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, 
	-15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, 
	-11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316, 
	 -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140, 
	 -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092, 
	 -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004, 
	 -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980, 
	 -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436, 
	 -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924, 
	  -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652, 
	  -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396, 
	  -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260, 
	  -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132, 
	  -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64, 
	   -56,    -48,    -40,    -32,    -24,    -16,     -8,      0, 
	 32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956, 
	 23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764, 
	 15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412, 
	 11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316, 
	  7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140, 
	  5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092, 
	  3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004, 
	  2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980, 
	  1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436, 
	  1372,   1308,   1244,   1180,   1116,   1052,    988,    924, 
	   876,    844,    812,    780,    748,    716,    684,    652, 
	   620,    588,    556,    524,    492,    460,    428,    396, 
	   372,    356,    340,    324,    308,    292,    276,    260, 
	   244,    228,    212,    196,    180,    164,    148,    132, 
	   120,    112,    104,     96,     88,     80,     72,     64, 
	    56,     48,     40,     32,     24,     16,      8,      0 };

    return ulaw_table[ulawbyte];
    }
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads