Audio Ring Buffer in C

An Audo Ring Buffer is nothing but a circular buffer,or ring buffer  data structre that uses a  fixed-size buffer as if it were connected end-to-end.

code :
AudioRingBuffer.h

#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/*
 * $Id: s_audio_paring.h,v 1.1 2004/09/06 20:20:35 millerpuckette Exp $
 * ringbuffer.h
 * Ring Buffer utility..
 *
 * Author: Phil Burk, http://www.softsynth.com
 *
 * This program is distributed with the PortAudio Portable Audio Library.
 * For more information see: http://www.audiomulch.com/portaudio/
 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <string.h>

typedef struct
{
    long   bufferSize; /* Number of bytes in FIFO. Power of 2. Set by RingBuffer_Init. */
/* These are declared volatile because they are written by a different thread than the reader. */
    volatile long   writeIndex; /* Index of next writable byte. Set by RingBuffer_AdvanceWriteIndex. */
    volatile long   readIndex;  /* Index of next readable byte. Set by RingBuffer_AdvanceReadIndex. */
    long   bigMask;    /* Used for wrapping indices with extra bit to distinguish full/empty. */
    long   smallMask;  /* Used for fitting indices to buffer. */
    char *buffer;
}
RingBuffer;
/*
 * Initialize Ring Buffer.
 * numBytes must be power of 2, returns -1 if not.
 */
long RingBuffer_Init( RingBuffer *rbuf, long numBytes, void *dataPtr );

/* Clear buffer. Should only be called when buffer is NOT being read. */
void RingBuffer_Flush( RingBuffer *rbuf );

/* Return number of bytes available for writing. */
long RingBuffer_GetWriteAvailable( RingBuffer *rbuf );
/* Return number of bytes available for read. */
long RingBuffer_GetReadAvailable( RingBuffer *rbuf );
/* Return bytes written. */
long RingBuffer_Write( RingBuffer *rbuf, const void *data, long numBytes );
/* Return bytes read. */
long RingBuffer_Read( RingBuffer *rbuf, void *data, long numBytes );

/* Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long RingBuffer_GetWriteRegions( RingBuffer *rbuf, long numBytes,
                                 void **dataPtr1, long *sizePtr1,
                                 void **dataPtr2, long *sizePtr2 );
long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes );

/* Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or numBytes, whichever is smaller.
*/
long RingBuffer_GetReadRegions( RingBuffer *rbuf, long numBytes,
                                void **dataPtr1, long *sizePtr1,
                                void **dataPtr2, long *sizePtr2 );

long RingBuffer_AdvanceReadIndex( RingBuffer *rbuf, long numBytes );

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _RINGBUFFER_H */


AudioRingBuffer.c
/*
 * $Id: s_audio_paring.c,v 1.1 2004/09/06 20:20:35 millerpuckette Exp $
 * ringbuffer.c
 * Ring Buffer utility..
 *
 * Author: Phil Burk, http://www.softsynth.com
 *
 * This program uses the PortAudio Portable Audio Library.
 * For more information see: http://www.audiomulch.com/portaudio/
 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
/*
 * modified 2002/07/13 by olaf.matthes@gmx.de to allow any number if channels
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "AudioRingBuffer.h"
#include <string.h>

/***************************************************************************
 * Initialize FIFO.
 */
long RingBuffer_Init( RingBuffer *rbuf, long numBytes, void *dataPtr )
{
    rbuf->bufferSize = numBytes;
    rbuf->buffer = (char *)dataPtr;
    RingBuffer_Flush( rbuf );
    return 0;
}
/***************************************************************************
** Return number of bytes available for reading. */
long RingBuffer_GetReadAvailable( RingBuffer *rbuf )
{
    long ret = rbuf->writeIndex - rbuf->readIndex;
    if (ret < 0)
        ret += 2 * rbuf->bufferSize;
    if (ret < 0 || ret > rbuf->bufferSize)
        fprintf(stderr,
            "consistency check failed: RingBuffer_GetReadAvailable\n");
    return ( ret );
}
/***************************************************************************
** Return number of bytes available for writing. */
long RingBuffer_GetWriteAvailable( RingBuffer *rbuf )
{
    return ( rbuf->bufferSize - RingBuffer_GetReadAvailable(rbuf));
}

/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read. */
void RingBuffer_Flush( RingBuffer *rbuf )
{
    rbuf->writeIndex = rbuf->readIndex = 0;
}

/***************************************************************************
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long RingBuffer_GetWriteRegions( RingBuffer *rbuf, long numBytes,
                                 void **dataPtr1, long *sizePtr1,
                                 void **dataPtr2, long *sizePtr2 )
{
    long   index;
    long   available = RingBuffer_GetWriteAvailable( rbuf );
    if( numBytes > available ) numBytes = available;
    /* Check to see if write is not contiguous. */
    index = rbuf->writeIndex;
    while (index >= rbuf->bufferSize)
        index -= rbuf->bufferSize;
    if( (index + numBytes) > rbuf->bufferSize )
    {
        /* Write data in two blocks that wrap the buffer. */
        long   firstHalf = rbuf->bufferSize - index;
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = firstHalf;
        *dataPtr2 = &rbuf->buffer[0];
        *sizePtr2 = numBytes - firstHalf;
    }
    else
    {
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = numBytes;
        *dataPtr2 = NULL;
        *sizePtr2 = 0;
    }
    return numBytes;
}


/***************************************************************************
*/
long RingBuffer_AdvanceWriteIndex( RingBuffer *rbuf, long numBytes )
{
    long ret = (rbuf->writeIndex + numBytes);
    if ( ret >= 2 * rbuf->bufferSize)
        ret -= 2 * rbuf->bufferSize;    /* check for end of buffer */
    return rbuf->writeIndex = ret;
}

/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long RingBuffer_GetReadRegions( RingBuffer *rbuf, long numBytes,
                                void **dataPtr1, long *sizePtr1,
                                void **dataPtr2, long *sizePtr2 )
{
    long   index;
    long   available = RingBuffer_GetReadAvailable( rbuf );
    if( numBytes > available ) numBytes = available;
    /* Check to see if read is not contiguous. */
    index = rbuf->readIndex;
    while (index >= rbuf->bufferSize)
        index -= rbuf->bufferSize;
   
    if( (index + numBytes) > rbuf->bufferSize )
    {
        /* Write data in two blocks that wrap the buffer. */
        long firstHalf = rbuf->bufferSize - index;
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = firstHalf;
        *dataPtr2 = &rbuf->buffer[0];
        *sizePtr2 = numBytes - firstHalf;
    }
    else
    {
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = numBytes;
        *dataPtr2 = NULL;
        *sizePtr2 = 0;
    }
    return numBytes;
}
/***************************************************************************
*/
long RingBuffer_AdvanceReadIndex( RingBuffer *rbuf, long numBytes )
{
    long ret = (rbuf->readIndex + numBytes);
    if( ret >= 2 * rbuf->bufferSize)
        ret -= 2 * rbuf->bufferSize;
    return rbuf->readIndex = ret;
}

/***************************************************************************
** Return bytes written. */
long RingBuffer_Write( RingBuffer *rbuf, const void *data, long numBytes )
{
    long size1, size2, numWritten;
    void *data1, *data2;
    numWritten = RingBuffer_GetWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
    if( size2 > 0 )
    {

        memcpy( data1, data, size1 );
        data = ((char *)data) + size1;
        memcpy( data2, data, size2 );
    }
    else
    {
        memcpy( data1, data, size1 );
    }
    RingBuffer_AdvanceWriteIndex( rbuf, numWritten );
    return numWritten;
}

/***************************************************************************
** Return bytes read. */
long RingBuffer_Read( RingBuffer *rbuf, void *data, long numBytes )
{
    long size1, size2, numRead;
    void *data1, *data2;
    numRead = RingBuffer_GetReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
    if( size2 > 0 )
    {
        memcpy( data, data1, size1 );
        data = ((char *)data) + size1;
        memcpy( data, data2, size2 );
    }
    else
    {
        memcpy( data, data1, size1 );
    }
    RingBuffer_AdvanceReadIndex( rbuf, numRead );
    return numRead;
}

Test Your C Skills


                     


 1) Shift the bits as illustrated above In the picture

     unsigned char A = 171;
     unsigned char B = 223;
     unsigned char C = 0;
     //Solution
     C = (A >> 3) | ((B >> 5) << 5);
     printf("A = %d , B = %d , C = %d ",A,B,C);


2) Find out the two logical Errors in the following code...

       
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  //Find out two logical Errors in the code
  typedef struct dbTable
  {
    char *key;
    int value;
  } dbTable;
  /* prototypes to get data from Hash table */
  int getData(dbTable *pdbTable , char *key);
  int getSize(dbTable *pdbTable);
  int main()
  {
    dbTable dbTableHash[] = {{"test1",1},{"test2",2},{"test3",3}, 
    {"test4",4},      {"test5",5},{"test6",6}};
    int value = getData(dbTableHash,"test6");
    printf("value = %d \n",value);
  }
  int getData(dbTable *pdbTable , char *key)
  {
    int i = 0;
    for(i = 0 ; i < sizeof(pdbTable) ; i++)
    {
        if(strcmp(pdbTable[i].key , key) == 0)
            break
    }
  
    return pdbTable[i].value;
  }
         
    

G.711 Audio Codec Explained

      G.711 is a high bit rate (64 Kbps) ITU standard codec. It is the native language of the modern digital telephone network.

     Although formally standardised in 1988, the G.711 PCM codec is the granddaddy of digital telephony. Invented by Bell Systems and introduced in the early 70's, the T1 digital trunk employed an 8-bit uncompressed Pulse Code Modulation encoding scheme with a sample rate of 8000 samples per second. This allowed for a (theoretical) maximum voice bandwith of 4000 Hz. A T1 trunk carries 24 digital PCM channels multiplexed together. The improved European E1 standard carries 30 channels.

                            

        There are two versions: A-law and U-law. U-law is indigenous to the T1 standard used in North America and Japan. The A-law is indigenous to the E1 standard used in the rest of the world. The difference is in the method the analog signal being sampled. In both schemes, the signal is not sampled linearly, but in a logarithmic fashion. A-law provides more dynamic range as opposed to U-law. The result is a less 'fuzzy' sound as sampling artifacts are better supressed.

Using G.711 for VoIP will give the best voice quality; since it uses no compression and it is the same codec used by the PSTN network and ISDN lines, it sounds just like using a regular or ISDN phone. It also has the lowest latency (lag) because there is no need for compression, which costs processing power. The downside is that it takes more bandwidth then other codecs, up to 84 Kbps including all TCP/IP overhead. However, with increasing broadband bandwith, this should not be a problem.

G.711 is supported by most VoIP providers.

/*                                                 Version 3.01 - 31.Jan.2000 
============================================================================= 

                          U    U   GGG    SSS  TTTTT 
                          U    U  G      S       T 
                          U    U  G  GG   SSS    T 
                          U    U  G   G      S   T 
                           UUUU    GGG    SSS    T 

                   ======================================== 
                    ITU-T - USER'S GROUP ON SOFTWARE TOOLS 
                   ======================================== 


       ============================================================= 
       COPYRIGHT NOTE: This source code, and all of its derivations, 
       is subject to the "ITU-T General Public License". Please have 
       it  read  in    the  distribution  disk,   or  in  the  ITU-T 
       Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND  AUDIO  
       CODING STANDARDS". 
       ============================================================= 


MODULE: G711.C, G.711 ENCODING/DECODING FUNCTIONS 

ORIGINAL BY: 

     Simao Ferraz de Campos Neto          Rudolf Hofmann 
     CPqD/Telebras                        PHILIPS KOMMUNIKATIONS INDUSTRIE AG 
     DDS/Pr.11                            Kommunikationssysteme 
     Rd. Mogi Mirim-Campinas Km.118       Thurn-und-Taxis-Strasse 14 
     13.085 - Campinas - SP (Brazil)      D-8500 Nuernberg 10 (Germany) 

     Phone : +55-192-39-6396              Phone : +49 911 526-2603 
     FAX   : +55-192-53-4754              FAX   : +49 911 526-3385 
     EMail : tdsimao@venus.cpqd.ansp.br   EMail : HF@PKINBG.UUCP 


FUNCTIONS: 

alaw_compress: ... compands 1 vector of linear PCM samples to A-law; 
                   uses 13 Most Sig.Bits (MSBs) from input and 8 Least 
                   Sig. Bits (LSBs) on output. 

alaw_expand: ..... expands 1 vector of A-law samples to linear PCM; 
                   use 8 Least Sig. Bits (LSBs) from input and 
                   13 Most Sig.Bits (MSBs) on output. 

ulaw_compress: ... compands 1 vector of linear PCM samples to u-law; 
                   uses 14 Most Sig.Bits (MSBs) from input and 8 Least 
                   Sig. Bits (LSBs) on output. 

ulaw_expand: ..... expands 1 vector of u-law samples to linear PCM 
                   use 8 Least Sig. Bits (LSBs) from input and 
                   14 Most Sig.Bits (MSBs) on output. 

PROTOTYPES: in g711.h 

HISTORY: 
Apr/91       1.0   First version of the G711 module 
10/Dec/1991  2.0   Break-up in individual functions for A,u law; 
                   correction of bug in compression routines (use of 1 
                   and 2 complement); Demo program inside module. 
08/Feb/1992  3.0   Demo as separate file; 
31/Jan/2000  3.01  Updated documentation text; no change in functions  
                   <simao.campos@labs.comsat.com> 
13jan2005          Byte for compressed data 
============================================================================= 
*/  
  
/* 
 *  .......... I N C L U D E S .......... 
 */  
  
/* Global prototype functions */  
#include "g711.h"  
  
/* 
 *  .......... F U N C T I O N S .......... 
 */  
  
/* ................... Begin of alaw_compress() ..................... */  
/* 
  ========================================================================== 

   FUNCTION NAME: alaw_compress 

   DESCRIPTION: ALaw encoding rule according ITU-T Rec. G.711. 

   PROTOTYPE: void alaw_compress(long lseg, short *linbuf, short *logbuf) 

   PARAMETERS: 
     lseg:  (In)  number of samples 
     linbuf:    (In)  buffer with linear samples (only 12 MSBits are taken 
                      into account) 
     logbuf:    (Out) buffer with compressed samples (8 bit right justified, 
                      without sign extension) 

   RETURN VALUE: none. 

   HISTORY: 
   10.Dec.91    1.0 Separated A-law compression function 

  ========================================================================== 
*/  
void alaw_compress(long lseg, short *linbuf, Byte *logbuf)  
{  
  short ix, iexp;  
  long n;  
  
  for (n = 0; n < lseg; n++) {  
    ix = linbuf[n] < 0          /* 0 <= ix < 2048 */  
      ? (~linbuf[n]) >> 4       /* 1's complement for negative values */  
      : (linbuf[n]) >> 4;  
  
    /* Do more, if exponent > 0 */  
    if (ix > 15) {              /* exponent=0 for ix <= 15 */  
      iexp = 1;                 /* first step: */  
      while (ix > 16 + 15) {    /* find mantissa and exponent */  
        ix >>= 1;  
        iexp++;  
      }  
      ix -= 16;                 /* second step: remove leading '1' */  
  
      ix += iexp << 4;          /* now compute encoded value */  
    }  
    if (linbuf[n] >= 0)  
      ix |= (0x0080);           /* add sign bit */  
  
    logbuf[n] = ix ^ (0x0055);  /* toggle even bits */  
  }  
}  
  
/* ................... End of alaw_compress() ..................... */  
  
  
/* ................... Begin of alaw_expand() ..................... */  
/* 
  ========================================================================== 

   FUNCTION NAME: alaw_expand 

   DESCRIPTION: ALaw decoding rule according ITU-T Rec. G.711. 

   PROTOTYPE: void alaw_expand(long lseg, short *logbuf, short *linbuf) 

   PARAMETERS: 
     lseg:  (In)  number of samples 
     logbuf:    (In)  buffer with compressed samples (8 bit right justified, 
                      without sign extension) 
     linbuf:    (Out) buffer with linear samples (13 bits left justified) 

   RETURN VALUE: none. 

   HISTORY: 
   10.Dec.91    1.0 Separated A-law expansion function 

  ============================================================================ 
*/  
void alaw_expand(long lseg, Byte *logbuf, short *linbuf)  
{  
  short ix, mant, iexp;  
  long n;  
  
  for (n = 0; n < lseg; n++) {  
    ix = logbuf[n] ^ (0x0055);  /* re-toggle toggled bits */  
  
    ix &= (0x007F);             /* remove sign bit */  
    iexp = ix >> 4;             /* extract exponent */  
    mant = ix & (0x000F);       /* now get mantissa */  
    if (iexp > 0)  
      mant = mant + 16;         /* add leading '1', if exponent > 0 */  
  
    mant = (mant << 4) + (0x0008);      /* now mantissa left justified and */  
    /* 1/2 quantization step added */  
    if (iexp > 1)               /* now left shift according exponent */  
      mant = mant << (iexp - 1);  
  
    linbuf[n] = logbuf[n] > 127 /* invert, if negative sample */  
      ? mant : -mant;  
  }  
}  
  
/* ................... End of alaw_expand() ..................... */  
  
  
/* ................... Begin of ulaw_compress() ..................... */  
/* 
  ========================================================================== 

   FUNCTION NAME: ulaw_compress 

   DESCRIPTION: Mu law encoding rule according ITU-T Rec. G.711. 

   PROTOTYPE: void ulaw_compress(long lseg, short *linbuf, short *logbuf) 

   PARAMETERS: 
     lseg:  (In)  number of samples 
     linbuf:    (In)  buffer with linear samples (only 12 MSBits are taken 
                      into account) 
     logbuf:    (Out) buffer with compressed samples (8 bit right justified, 
                      without sign extension) 

   RETURN VALUE: none. 

   HISTORY: 
   10.Dec.91    1.0 Separated mu-law compression function 

  ========================================================================== 
*/  
void ulaw_compress(long lseg, short *linbuf, Byte *logbuf)  
{  
  long n;                       /* samples's count */  
  short i;                      /* aux.var. */  
  short absno;                  /* absolute value of linear (input) sample */  
  short segno;                  /* segment (Table 2/G711, column 1) */  
  short low_nibble;             /* low  nibble of log companded sample */  
  short high_nibble;            /* high nibble of log companded sample */  
  
  for (n = 0; n < lseg; n++) {  
    /* -------------------------------------------------------------------- */  
    /* Change from 14 bit left justified to 14 bit right justified */  
    /* Compute absolute value; adjust for easy processing */  
    /* -------------------------------------------------------------------- */  
    absno = linbuf[n] < 0       /* compute 1's complement in case of  */  
      ? ((~linbuf[n]) >> 2) + 33        /* negative samples */  
      : ((linbuf[n]) >> 2) + 33;        /* NB: 33 is the difference value */  
    /* between the thresholds for */  
    /* A-law and u-law. */  
    if (absno > (0x1FFF))       /* limitation to "absno" < 8192 */  
      absno = (0x1FFF);  
  
    /* Determination of sample's segment */  
    i = absno >> 6;  
    segno = 1;  
    while (i != 0) {  
      segno++;  
      i >>= 1;  
    }  
  
    /* Mounting the high-nibble of the log-PCM sample */  
    high_nibble = (0x0008) - segno;  
  
    /* Mounting the low-nibble of the log PCM sample */  
    low_nibble = (absno >> segno)       /* right shift of mantissa and */  
      &(0x000F);                /* masking away leading '1' */  
    low_nibble = (0x000F) - low_nibble;  
  
    /* Joining the high-nibble and the low-nibble of the log PCM sample */  
    logbuf[n] = (high_nibble << 4) | low_nibble;  
  
    /* Add sign bit */  
    if (linbuf[n] >= 0)  
      logbuf[n] = logbuf[n] | (0x0080);  
  }  
}  
  
/* ................... End of ulaw_compress() ..................... */  
  
  
  
/* ................... Begin of ulaw_expand() ..................... */  
/* 
  ========================================================================== 

   FUNCTION NAME: ulaw_expand 

   DESCRIPTION: Mu law decoding rule according ITU-T Rec. G.711. 

   PROTOTYPE: void ulaw_expand(long lseg, short *logbuf, short *linbuf) 

   PARAMETERS: 
     lseg:  (In)  number of samples 
     logbuf:    (In)  buffer with compressed samples (8 bit right justified, 
                      without sign extension) 
     linbuf:    (Out) buffer with linear samples (14 bits left justified) 

   RETURN VALUE: none. 

   HISTORY: 
   10.Dec.91    1.0 Separated mu law expansion function 

  ============================================================================ 
*/  
  
void ulaw_expand(long lseg, Byte *logbuf, short *linbuf)  
{  
  long n;                       /* aux.var. */  
  short segment;                /* segment (Table 2/G711, column 1) */  
  short mantissa;               /* low  nibble of log companded sample */  
  short exponent;               /* high nibble of log companded sample */  
  short sign;                   /* sign of output sample */  
  short step;  
  
  for (n = 0; n < lseg; n++) {  
    sign = logbuf[n] < (0x0080) /* sign-bit = 1 for positiv values */  
      ? -1 : 1;  
    mantissa = ~logbuf[n];      /* 1's complement of input value */  
    exponent = (mantissa >> 4) & (0x0007);      /* extract exponent */  
    segment = exponent + 1;     /* compute segment number */  
    mantissa = mantissa & (0x000F);     /* extract mantissa */  
  
    /* Compute Quantized Sample (14 bit left justified!) */  
    step = (4) << segment;      /* position of the LSB */  
    /* = 1 quantization step) */  
    linbuf[n] = sign *          /* sign */  
      (((0x0080) << exponent)   /* '1', preceding the mantissa */  
      +step * mantissa          /* left shift of mantissa */  
      + step / 2                /* 1/2 quantization step */  
      - 4 * 33);  
  }  
}  
  
/* ................... End of ulaw_expand() ..................... */
PCM to mu-law & a-law , a-law & mu-law to PCM conversion
Code Conversion Utility:
PCM to mu-law & a-law , a-law & mu-law to PCM conversion
/*
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use.  Users may copy or modify this source code without
 * charge.
 *
 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * Sun source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even if
 * Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

/*
 * g711.c
 *
 * u-law, A-law and linear PCM conversions.
 */
#define SIGN_BIT (0x80)  /* Sign bit for a A-law byte. */
#define QUANT_MASK (0xf)  /* Quantization field mask. */
#define NSEGS  (8)  /* Number of A-law segments. */
#define SEG_SHIFT (4)  /* Left shift for segment number. */
#define SEG_MASK (0x70)  /* Segment field mask. */

static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
       0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};

/* copy from CCITT G.711 specifications */
unsigned char _u2a[128] = {   /* u- to A-law conversions */
 1, 1, 2, 2, 3, 3, 4, 4,
 5, 5, 6, 6, 7, 7, 8, 8,
 9, 10, 11, 12, 13, 14, 15, 16,
 17, 18, 19, 20, 21, 22, 23, 24,
 25, 27, 29, 31, 33, 34, 35, 36,
 37, 38, 39, 40, 41, 42, 43, 44,
 46, 48, 49, 50, 51, 52, 53, 54,
 55, 56, 57, 58, 59, 60, 61, 62,
 64, 65, 66, 67, 68, 69, 70, 71,
 72, 73, 74, 75, 76, 77, 78, 79,
 81, 82, 83, 84, 85, 86, 87, 88,
 89, 90, 91, 92, 93, 94, 95, 96,
 97, 98, 99, 100, 101, 102, 103, 104,
 105, 106, 107, 108, 109, 110, 111, 112,
 113, 114, 115, 116, 117, 118, 119, 120,
 121, 122, 123, 124, 125, 126, 127, 128};

unsigned char _a2u[128] = {   /* A- to u-law conversions */
 1, 3, 5, 7, 9, 11, 13, 15,
 16, 17, 18, 19, 20, 21, 22, 23,
 24, 25, 26, 27, 28, 29, 30, 31,
 32, 32, 33, 33, 34, 34, 35, 35,
 36, 37, 38, 39, 40, 41, 42, 43,
 44, 45, 46, 47, 48, 48, 49, 49,
 50, 51, 52, 53, 54, 55, 56, 57,
 58, 59, 60, 61, 62, 63, 64, 64,
 65, 66, 67, 68, 69, 70, 71, 72,
 73, 74, 75, 76, 77, 78, 79, 79,
 80, 81, 82, 83, 84, 85, 86, 87,
 88, 89, 90, 91, 92, 93, 94, 95,
 96, 97, 98, 99, 100, 101, 102, 103,
 104, 105, 106, 107, 108, 109, 110, 111,
 112, 113, 114, 115, 116, 117, 118, 119,
 120, 121, 122, 123, 124, 125, 126, 127};

static int
search(
 int  val,
 short  *table,
 int  size)//size=8
{
 int  i;

 for (i = 0; i < size; i++) {
  if (val <= *table++)
   return (i);
 }
 return (size);
}

/*
 * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
 *
 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
 *
 *  Linear Input Code Compressed Code
 * ------------------------ ---------------
 * 0000,000w,xyza   000wxyz
 * 0000,001w,xyza   001wxyz
 * 0000,01wx,yzab   010wxyz
 * 00001wxyzabc   011wxyz
 * 0001wxyzabcd   100wxyz
 * 001wxyzabcde   101wxyz
 * 01wxyzabcdef   110wxyz
 * 1wxyzabcdefg   111wxyz
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 */
unsigned char
linear2alaw(
 int  pcm_val) /* 2's complement (16-bit range) */
{
 int  mask;
 int  seg;
 unsigned char aval;

 if (pcm_val >= 0) {
  mask = 0xD5;  /* sign (7th) bit = 1 */
 } else {
  mask = 0x55;  /* sign bit = 0 */
  pcm_val = -pcm_val - 8;
 }

 /* Convert the scaled magnitude to segment number. */
 seg = search(pcm_val, seg_end, 8);

 /* Combine the sign, segment, and quantization bits. */

 if (seg >= 8)  /* out of range, return maximum value. */
  return (0x7F ^ mask);
 else {
  aval = seg << SEG_SHIFT;
  if (seg < 2)
   aval |= (pcm_val >> 4) & QUANT_MASK;
  else
   aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
  return (aval ^ mask);
 }
}

/*
 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
 *
 */
int
alaw2linear(
 unsigned char a_val)
{
 int  t;
 int  seg;

 a_val ^= 0x55;

 t = (a_val & QUANT_MASK) << 4;
 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
 switch (seg) {
 case 0:
  t += 8;
  break;
 case 1:
  t += 0x108;
  break;
 default:
  t += 0x108;
  t <<= seg - 1;
 }
 return ((a_val & SIGN_BIT) ? t : -t);
}

#define BIAS  (0x84)  /* Bias for linear code. */

/*
 * linear2ulaw() - Convert a linear PCM value to u-law
 *
 * In order to simplify the encoding process, the original linear magnitude
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 * (33 - 8191). The result can be seen in the following encoding table:
 *
 * Biased Linear Input Code Compressed Code
 * ------------------------ ---------------
 * 00000001wxyza   000wxyz
 * 0000001wxyzab   001wxyz
 * 000001wxyzabc   010wxyz
 * 00001wxyzabcd   011wxyz
 * 0001wxyzabcde   100wxyz
 * 001wxyzabcdef   101wxyz
 * 01wxyzabcdefg   110wxyz
 * 1wxyzabcdefgh   111wxyz
 *
 * Each biased linear code has a leading 1 which identifies the segment
 * number. The value of the segment number is equal to 7 minus the number
 * of leading 0's. The quantization interval is directly available as the
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 *
 * Ordinarily the complement of the resulting code word is used for
 * transmission, and so the code word is complemented before it is returned.
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 */
unsigned char
linear2ulaw(
 int  pcm_val) /* 2's complement (16-bit range) */
{
 int  mask;
 int  seg;
 unsigned char uval;

 /* Get the sign and the magnitude of the value. */
 if (pcm_val < 0) {
  pcm_val = BIAS - pcm_val;
  mask = 0x7F;
 } else {
  pcm_val += BIAS;
  mask = 0xFF;
 }

 /* Convert the scaled magnitude to segment number. */
 seg = search(pcm_val, seg_end, 8);

 /*
  * Combine the sign, segment, quantization bits;
  * and complement the code word.
  */
 if (seg >= 8)  /* out of range, return maximum value. */
  return (0x7F ^ mask);
 else {
  uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
  return (uval ^ mask);
 }

}

/*
 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
 *
 * First, a biased linear code is derived from the code word. An unbiased
 * output can then be obtained by subtracting 33 from the biased code.
 *
 * Note that this function expects to be passed the complement of the
 * original code word. This is in keeping with ISDN conventions.
 */
int
ulaw2linear(
 unsigned char u_val)
{
 int  t;

 /* Complement to obtain normal u-law value. */
 u_val = ~u_val;

 /*
  * Extract and bias the quantization bits. Then
  * shift up by the segment number and subtract out the bias.
  */
 t = ((u_val & QUANT_MASK) << 3) + BIAS;
 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;

 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}

/* A-law to u-law conversion */
unsigned char
alaw2ulaw(
 unsigned char aval)
{
 aval &= 0xff;
 return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
     (0x7F ^ _a2u[aval ^ 0x55]));
}

/* u-law to A-law conversion */
unsigned char
ulaw2alaw(
 unsigned char uval)
{
 uval &= 0xff;
 return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
     (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
}