Newsgroups: comp.speech
Path: pavo.csi.cam.ac.uk!warwick!pipex!sunic!trane.uninett.no!nuug!nntp.nta.no!hal.nta.no!hlj
From: hlj@hal.nta.no (Harald Ljoen FBA)
Subject: Re: conversion A-law <-> linear and A-law <-> U-law ?
Message-ID: <1993Jun14.143459.29236@nntp.nta.no>
Keywords: A-law,U-law
Sender: news@nntp.nta.no
Nntp-Posting-Host: titan.nta.no
Reply-To: harald.ljoen@tf.tele.no
Organization: Norwegian Telecom Research
References:  <1vcdqo$gg9@news.cs.tu-berlin.de>
Date: Mon, 14 Jun 93 14:34:59 GMT
Lines: 194

In article <1vcdqo$gg9@news.cs.tu-berlin.de>, tilo@cs.tu-berlin.de (Tilo Schuerer) writes:
>
>
>Hy Neters,
>
>I'm looking for some C-routines which convert
>
>    o  A-law (8bit)  to/from linear (16bit)
>    o  A-law (8bit)  to/from U-law (8bit)

The following should fullfill your needs. After getting no response from
a similar posting in this newsgroup a year ago, I found I had to write it
myself.

-- 
** Also sprach harald.ljoen@tf.tele.no **

--8<------8<------8<------8<------8<------8<------8<------8<------8<----
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	pcmAlaw.c
#	pcmAlaw.h
#
echo x - pcmAlaw.c
sed 's/^X//' >pcmAlaw.c << 'END-of-pcmAlaw.c'
X/* 
X   Copyright (c) 1992 by Harald Ljoen, Norwegian Telecom Research.
X   This code may be used and redistributed as described in the terms of the GNU
X   General Public Licence as published by the Free Software Foundation.
X
X
X   File:       pcmAlaw.c
X   Purpose:    convert from linear or u-law PCM to and from A-law PCM
X   Reference:  CCITT recommendation G.711
X   Author:     Harald Ljoen, Norwegian Telecom Research
X               E-mail: harald.ljoen@tf.tele.no, or hlj@nta.no
X               Phone: +47 63 80 91 70, Fax: +47 63 81 00 76
X   Functions:
X         int pcmA_set_bits(int nbits)
X            nbits: the number of bits in linear samples that are input to
X               lin2pcmA() and returned from pcmA2lin(). Can be set to anything
X               between 13 and CHAR_BITS*sizeof(int), where CHAR_BITS is the number
X               of bit in a char. Default is 16 bits per linear sample. Note that
X               this does not effect the precision, which is always 13 bits, rather,
X               it determines which bits (lsb's or msb's) that are not used. Normally,
X               it's convenient to set nbits to either 16 (the default) or the number
X               of bits in your int. 
X            returns: the number of bits that will be used for future calls to
X               lin2pcmA() and pcmA2lin().
X         
X         unsigned char lin2pcmA(int samp)
X            samp: linear sample
X            returns: A-law coded PCM sample
X
X         int pcmA2lin(unsigned char pcm)
X            pcm: A-law coded PCM sample
X            returns: linear sample
X
X         unsigned char pcmA2u(unsigned char AlawSample)
X            AlawSample: A-law coded PCM sample
X            returns: u-law coded PCM sample
X
X         unsigned char pcmu2A(unsigned char ulawSample)
X            ulawSample: u-law coded PCM sample
X            returns: A-law coded PCM sample
X      
X*/
X
X#define CHAR_BITS 8           /* Change this if your char is not 8 bits wide */
X#define MAX_MAGNITUDE ((unsigned)(1 << (12 + plusbits)) - 1)
X
Xstatic int plusbits = 3;            /* default 13 + 3 = 16 bits/sample */
X
Xint pcmA_set_bits(nbits)
Xint nbits;
X{
X   if ((nbits >= 13) && (nbits <= CHAR_BITS*sizeof(int))) plusbits = nbits - 13;
X   return(plusbits + 13);
X}
X
Xunsigned char lin2pcmA(samp)
Xint samp;
X{
X/*
X   Quantization segment limits:  0..32..64..128..256..512..1024..2048..4096
X   Quantization step sizes:       2   2   4    8    16   32    64    128
X*/
X   int seg, seglimit, sign, mant;
X   unsigned char pcmA;
X
X   sign = (samp >= 0);
X   if (!sign) samp = -samp;
X   if (samp > MAX_MAGNITUDE) samp = MAX_MAGNITUDE;
X   seglimit = 1 << (5+plusbits);
X   seg = 0;
X   while (seglimit <= samp) {
X      seglimit <<= 1;
X      seg++;
X   }
X   mant = (samp >> ((seg == 0) ? 1 + plusbits : seg + plusbits)) & 0xf;
X   pcmA = (sign << 7) | (seg << 4) | mant;
X   return(pcmA ^ 0x55);
X}
X
Xint pcmA2lin(pcm)
Xunsigned char pcm;
X{
X   int samp, mant, seg, sign;
X
X   pcm ^= 0x55;
X   mant = pcm & 0xf;
X   seg = (pcm >> 4) & 0x7;
X   if (seg > 0) mant |= 0x10;
X   sign = !(pcm >> 7);
X
X   samp = ((mant << 1) + 1);
X   if (seg > 1) samp <<= seg - 1;
X   samp = sign ? -samp : samp;
X   return(samp << plusbits);
X}
X
Xunsigned char pcmA2u(AlawSample)
Xunsigned char AlawSample;
X{
X   unsigned char ulawSample, sign = AlawSample & 0x80;
X
X   AlawSample = (AlawSample ^ 0x55) & 0x7f;
X   if      (AlawSample > 78) ulawSample = AlawSample;
X   else if (AlawSample > 62) ulawSample = AlawSample + 1;
X   else if (AlawSample > 46) ulawSample = AlawSample + 2;
X   else if (AlawSample > 44) ulawSample = AlawSample + 3;
X   else if (AlawSample > 30) ulawSample = AlawSample + 4;
X   else if (AlawSample > 28) ulawSample = AlawSample + 5;
X   else if (AlawSample > 26) ulawSample = AlawSample + 6;
X   else if (AlawSample > 24) ulawSample = AlawSample + 7;
X   else if (AlawSample >  7) ulawSample = AlawSample + 8;
X   else                      ulawSample = 2 * AlawSample + 1;
X   return((~ulawSample & 0x7f) | sign);
X}
X
Xunsigned char pcmu2A(ulawSample)
Xunsigned char ulawSample;
X{
X   unsigned char AlawSample, sign = ulawSample & 0x80;
X
X   ulawSample = ~ulawSample & 0x7f;
X   if      (ulawSample > 79) AlawSample = ulawSample;
X   else if (ulawSample > 63) AlawSample = ulawSample - 1;
X   else if (ulawSample > 48) AlawSample = ulawSample - 2;
X   else if (ulawSample > 47) AlawSample = ulawSample - 3;
X   else if (ulawSample > 35) AlawSample = ulawSample - 4;
X   else if (ulawSample > 34) AlawSample = ulawSample - 5;
X   else if (ulawSample > 33) AlawSample = ulawSample - 6;
X   else if (ulawSample > 32) AlawSample = ulawSample - 7;
X   else if (ulawSample > 16) AlawSample = ulawSample - 8;
X   else                      AlawSample = ulawSample/2;
X   return((AlawSample | sign) ^ 0x55);
X}
END-of-pcmAlaw.c
echo x - pcmAlaw.h
sed 's/^X//' >pcmAlaw.h << 'END-of-pcmAlaw.h'
X/*
X   Copyright (c) 1992 by Harald Ljoen, Norwegian Telecom Research.
X   This code may be used and redistributed as described in the terms of the GNU
X   General Public Licence as published by the Free Software Foundation.
X
X   Author:     Harald Ljoen, Norwegian Telecom Research
X               E-mail: harald.ljoen@tf.tele.no, or hlj@nta.no
X               Phone: +47 63 80 91 70, Fax: +47 63 81 00 76
X*/
X
X#ifndef _pcmAlaw_h
X
X#ifdef __STDC__
Xint pcmA_set_bits(int nbits);
Xint pcmA2lin(unsigned char pcm);
Xunsigned char pcmA2u(unsigned char AlawSample);
Xunsigned char pcmu2A(unsigned char ulawSample);
X#else
Xint pcmA_set_bits();
Xint pcmA2lin();
Xunsigned char pcmA2u();
Xunsigned char pcmu2A();
X#endif
X
X#define _pcmAlaw_h
X#endif
END-of-pcmAlaw.h
exit
