Lookup tables in c(LUT in c) :

              In Embedded Systems computing execution time is an important factor deciding the performance of the device.Look up tables are used to maximize the execution speed of the embedded code to get the desired performance.

             A simple term used to explain the lookup table , we can say it a pre-computed table which has some calculated values in it.say for example an array of intergers contains calculated values starting from initial  to its maximum size.

       An simple illustrative code example,
#include 
//#include "LUT.h"

static double sqrtMag[256];
/* API's */
void initSqrtValues(void);

int main(int argc,char *argv[])
{
 //unsigned long int x = 0x1234;
 initSqrtValues();
 printf("LookUpTables in c usage:\n");
 /* Get the square root values from the precomputed lookuptables */
    printf(" Square root of %d from lookuptable = %f \n",5,sqrtMag[5]);
 printf(" Square root of %d from lookuptable = %f \n",10,sqrtMag[10]);
 //printf(" x before endian conversion : %x \n x after endian conversion = %x \n",x,ByteSwap2(x));
     
 return 0;
}

void initSqrtValues(void)
{
  int i ,len = (sizeof(sqrtMag)/sizeof(sqrtMag[0]));
  for ( i = 1; i < len ; i++)
  {
   sqrtMag[i] = (i);
   printf("sqrtMag[%d] = %f \n",i,sqrtMag[i]);
  }
}

Questions ? Ask here..

Any questions regarding postings or new requests dont hesitate to ask here..

Goertzel(modified FFT) algorithm implementation in c

 Goertzel(modified FFT) algorithm :

     The Goertzel algorithm is used to detect DTMF tones in telecom(Dual Tone Multi Frequency) with less CPU hourse power than the traditional FFT algorithm.

     I assume all the readers are well known of the algorithm so i give you example code api to implement it
/* Add FFT,Goertzel,Chirpz filtering techniques here */

/**************** 1. Goerzel method ***************************************
Description:
audioBlockSize : Size of the audio block (number of samples to be processed)
audioBuffer    : Actual samples of audio data (double)
sampleFreq     : Sample Rate or sampling Frequency (CCITT - telephone voice )
                 8000 Samples per second

targetFrequency: The frquency to test whether it lies in the sample block of processing
Energy value   : Magniture squared outpput value which will futher used to set
                 Threshold

Fix this       :---------
***************************************************************************/

double goerzelFilter(unsigned short audioBlockSize,  /* CCITT standard block Size */
                     double *audioRingBuffer,        /* Circular Audio Samples Buffer Input */
                     unsigned int SamplingFrequency, /* Sampling Rate of the Sampled signal */
                     unsigned int targetFrequency,   /* Which Frequency range want to detect */
                     int EnergyValue)                /* total Energy value Threshold to detect the Frequency range */
{

    /* Init Goertzel Filter  */
    int j = 0;
    double omega;
    int k;
    double cosines;
    double p;
    float Q0;
    float Q1;
    float Q2;
    double magnitude;

    //coefficient calculation;
    k = (int)(0.5 + ((audioBlockSize * targetFrequency)/ SamplingFrequency));
    omega   = ((2 * PI)/ audioBlockSize) * k;
    cosines = cos(omega);
    p = 2.0 * cosines;

    //goertzel detetion
    Q1 = 0.0;
    Q2 = 0.0;
    for(j = 0; j < audioBlockSize ; j++)
    {
        Q0 = (p * Q1)- (Q2 + audioRingBuffer[j]);
        Q2 = Q1;
        Q1 = Q0;
    }
    magnitude = sqrt(Q1 * Q1 + Q2 * Q2 - (Q1 * Q2 * p));
}


Embedded C,RTOS interview questions with answers


Recommended Embedded RTOS books to buy:
1) What is RTOS and why do we go for it?
       RTOS sheludes execution in a timely manner,manages system resources and provides a consistent foundation for developing application code.
     Application code designed for RTOS could be ranging from simple digital stopwatch to complex aircraft navigation systems.
RTOS differs from the GPOS by
  Task scheduling : RTOS like vxWorks,neclueos, uC/OSII uses a strict scheduling algorithms (like pre-emptive scheduling) that makes the tasks meet their deadline to get the job done.
  The sheduler decides which task run when by knowing its priorities.Whereas In a GPOS, the scheduler typically uses a "fairness" policy that offers no assurances that high-priority, time-critical tasks will execute in preference to lower-priority tasks.This policy is maintained to obtain the overall output by the desktop pc or server pc.

2) What are the different types of semaphores in vxworks RTOS? Which is the fastest?
       VxWorks supports three types of semaphores.
 1) Binary 2) mutual exclusion, and 3)counting semaphores.
 Fastest : Binary semaphore.


         3. What is priority inversion ? why priority inversion occurs?
     Tasks in RTOS's communucates between them via IPC source semphores for synchornization.
     The situation priority inversion occurs when a higher priority taks is ready to run but it is waiting for a shared resource that is to be released by a lower priority task currently running .Now higher-priority task is pending on the resource and it has to wait until the lower priority task to finish.
4. What are the solutions for priority inversion ?

    1) Priority inheritance
    2) Priority ceiling

5. What is super loop ?

      Super loop is the infinite loop that runs all the time because , most of the embedded systems has no OS in it to return to application.
//Super loop example
while(true)
{
 //all other code
}

//or

for(;;)
{
}

//or

label:
//This is is tricky assembly version
goto label:


6) What is the difference between Structure and union? Where do we use union?

        When a structure is defined the compiler allocates memory for all of its member variables with necessary alignment .Whereas for unions the compiler allocates memory for the highest the union is equal to the biggest size of member from the union member variable list.union can only store information in one field at any one time.
#include <stdio.h>
struct mStruct
{
    char name[10];
    int age;
    float height;
};

union mUnion
{
    char name[15];
    int age;
    float height;
};

int main(void)
{
    union  mUnion  uTest;
    struct mStruct sTest;
    strcpy(sTest.name,"sTest");
    sTest.age    = 20;
    sTest.height = 6.1;
    strcpy(uTest.name ,"uTest");
    uTest.height = 6.0;
    uTest.age    = 20;
    printf("\n");
    printf("sizeof(uTest) = %d ,sizeof(sTest) = %d \n",sizeof(uTest),sizeof(sTest));
    printf("uTest.age = %d , uTest.height = %f , uTest.name = %s\n",uTest.age, uTest.height, uTest.name);
    printf("sTest.age = %d , sTest.height = %f , sTest.name = %s\n",sTest.age, sTest.height, sTest.name);
    printf("\n");
}
7) Convert number 2 --> 37 without using any other operator but bitwise ? 
Answer:
    int x = 2;
    printf("X before :%d\n",x);
    x = (x<<x<<x) | (x<<x<<x) |  x<<!!x | !!x ;
    printf("X After  :%d\n",x); 

 

8) Set , Get , Clear ,Toggle , Display Bits ?
// Display Every bits in a int number 
void displayBits(int data)
{
    int dataSize = 1<<sizeof(data);
    int count = 0;
    for (count = dataSize;count >= 0; count--)
    {
        printf("%d",(testBit(data,count)));
    }
}
// test a bit if it is zero or one 
int8_t testBit(int8_t value,int whichBit)
{
    int mask = 1 << whichBit;
    if (value&mask)
    {
        return TRUE;
    }
    else return FALSE;
}

// Set a bit to one 
int8_t setBit(int8_t result, int whichBit)
{
    return (result |= (1<<whichBit));
}

// toggle a bit  
int8_t toggleBit(int8_t result, int whichBit)
{
    return (result ^= (1<<whichBit));
}

/* Clear a bit to zero */
int8_t clearBit(int8_t result, int whichBit)
{
    return (result &=~ (1<<whichBit));
}

Litte Endian , Big Endian Formats in C

    Endianness is byte ordering used to store the data in memory ie which byte has to be stored at the lower order address or the higher address.Here is a simple code given to determine the platform is which endian type.
==========
#include <stdio.h>
#include <stdlib.h>
#define STR_LIM (5)
#define STR_MAX_SIZE (256)

enum endian
{
    eBIG_ENDIAN,
    eLITTLE_ENDIAN,
};
char *int2char(int value);
int findEndian(int data);

int main()
{
    char string[STR_LIM] = "TEST";
    char testStr[5];
    int  number = 2048;
    printf(" Address : Value Representation\n");
    printf("-------------------------------\n");
    printf("%d:%c , %d:%c, %d:%c, %d:%c \n",&string[0],string[0],&string[1],string[1],&string[2],string[2],&string[3],string[3]);
    strcpy(testStr,int2char(number));
    printf("%d:%c , %d:%c, %d:%c, %d:%c \n",&testStr[0],testStr[0],&testStr[1],testStr[1],&testStr[2],testStr[2],&testStr[3],testStr[3]);
    if(findEndian(1))
    printf("LITTLE Endian Platform found\n");
    else printf("BIG Endian Platform found\n");
    return(getchar());
}

/* Integer to char conversion */
char *int2char(int value)
{
    static char string[STR_MAX_SIZE];
    sprintf(string,"%d",value);
    return string;
}

/* Check Which Endian the Platform is */
int findEndian(int data)
{
    char *charData;
    int ret = eLITTLE_ENDIAN;
    charData = (char *) &data;
    if(charData[0] == eBIG_ENDIAN)
    ret = eBIG_ENDIAN;
    return ret;
}

Linked Lists Explored...

 
Append Node to the List:
    Appending involves add Node to the end of the Linked List , consider doubly linked list provided in the below example code ,

This is the Node looks like :


Code Example:
===========
#include <stdio.h>
#include <stdlib.h>

 
typedef struct sList
{
    char *name;
    struct sList *next_sList;
    struct sList *prev_sList;
} UtilList;


#define MAX_NAME_SIZE 255
/* Generic Operations done in Doubly Linked List - API's */
void utilAppendList(char *name,UtilList **pUtilList);
void utilAddListAtHead(char *name,UtilList **pUtilList);
int  utilRemoveSpecList(UtilList **pUtilList,int listnum2delete);
void utilRemoveList(UtilList **pUtilList);
void utilReverseList(UtilList **pUtilList);
void displayList(UtilList *pUtilList);

/* Other Operations */
void utilSortList(UtilList **pUtilList);
void utilSwapDList(UtilList **pxUtilList,UtilList **pyUtilList);

int main()
{
    char *name[] = {"Test1","Test2","Test3","Test4","Test5"};
    UtilList *pUtilList = NULL;
    /* Add List at Head Node */
    printf("Adding Node at Head Node\n");
    utilAddListAtHead(name[0],&pUtilList);
    utilAddListAtHead(name[1],&pUtilList);
    utilAddListAtHead(name[2],&pUtilList);
    utilAddListAtHead(name[3],&pUtilList);
    utilAddListAtHead(name[4],&pUtilList);
    displayList(pUtilList);
    /* Add List at End */
    printf("Add List at End\n");
    utilAppendList(name[0],&pUtilList);
    utilAppendList(name[1],&pUtilList);
    utilAppendList(name[2],&pUtilList);
    /* Remove a Specified list at given location */
    utilRemoveSpecList(&pUtilList,2);
    utilAppendList(name[3],&pUtilList);
    utilAppendList(name[4],&pUtilList);
    printf("Display list after added both at Head and End\n");
    displayList(pUtilList);
    /* Reversiong List */
    utilRemoveList(&pUtilList);
    printf("After Removing List :\n");
    displayList(pUtilList);
    /* Issues based on appendList */
    return(0);
}

void utilAppendList(char *name,UtilList **pUtilList)
{
    UtilList *ptempUtilList    = (UtilList *)malloc(sizeof(UtilList));
    UtilList *ptempUtilEnd     = NULL;
    if(!(*pUtilList))
    {
        ptempUtilList->name       = (char *)malloc(sizeof(char)* MAX_NAME_SIZE);
        strcpy(ptempUtilList->name,name);
        ptempUtilList->next_sList = NULL;
        ptempUtilList->prev_sList = NULL;
        *pUtilList = ptempUtilList;
    }
    else
    {
        ptempUtilList->name       = (char *)malloc(MAX_NAME_SIZE * sizeof(char));
        ptempUtilEnd              = *pUtilList;
        strcpy(ptempUtilList->name,name);
        while(ptempUtilEnd->next_sList)
        {
            ptempUtilEnd = ptempUtilEnd->next_sList;
        }
        ptempUtilList->prev_sList = ptempUtilEnd;
        ptempUtilList->next_sList = NULL;
        ptempUtilEnd->next_sList  = ptempUtilList;
    }
}

void utilAddListAtHead(char *name,UtilList **pUtilList)
{
    UtilList *ptempUtilList    = (UtilList *)malloc(sizeof(UtilList));
    UtilList *ptempUtilHead    = NULL;
    if(!(*pUtilList))
    {
        ptempUtilList->name       = (char *)malloc(sizeof(char) * MAX_NAME_SIZE);
        strcpy(ptempUtilList->name,name);
        ptempUtilList->next_sList = NULL;
        ptempUtilList->prev_sList = NULL;
        *pUtilList = ptempUtilList;
    }
    else
    {
        ptempUtilList->name       = (char *)malloc(MAX_NAME_SIZE * sizeof(char));
        strcpy(ptempUtilList->name,name);
        (*pUtilList)->prev_sList  = ptempUtilList;
        ptempUtilList->next_sList = *pUtilList;
        *pUtilList = ptempUtilList;
    }
}

void displayList(UtilList *pUtilList)
{
    UtilList *ptempUtilList = pUtilList;
    if(ptempUtilList)
    {
        while(ptempUtilList)
        {
            printf("Name = %s \n",ptempUtilList->name);
            ptempUtilList = ptempUtilList->next_sList;
        }
    }
    else
    {
        printf("List is empty\n");
    }

}

void utilRemoveList(UtilList **pUtilList)
{
    UtilList *pCurrUtilList = NULL;
    while(*pUtilList)
    {
        pCurrUtilList = *pUtilList;
        *pUtilList    = (*pUtilList)->next_sList;
        free(pCurrUtilList->name);
        free(pCurrUtilList);
    }
    *pUtilList = NULL;
}

int utilRemoveSpecList(UtilList **pUtilList,int listnum2delete)
{
    UtilList *pCurrUtilList = *pUtilList;
    int ret                 = 0;
    int count               = 1;

    while((pCurrUtilList) && (count != listnum2delete))
    {
        pCurrUtilList    = pCurrUtilList->next_sList;
        count++;
        ret = 1;
    }
    (*pUtilList)->next_sList = (*pUtilList)->next_sList->next_sList;
    (*pUtilList)->prev_sList = (*pUtilList);
    free(pCurrUtilList->name) ;
    free(pCurrUtilList);
    return ret;
}

void utilSortList(UtilList **pUtilList)
{

}

void utilSwapDList(UtilList **pxUtilList,UtilList **pyUtilList)
{
    UtilList *ptempUtilList = NULL;

}

How to read wav file header in C#

    Reading header information from a wav file is discussed with example code in detail in this blog
(http://www.techband.in/2011/01/how-to-read-wavfile-header-in-c.html).
Here is the C# version of reading header info from a Microsoft specific wav file .

    This class can be used to get  wav header details , show the code below...


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.IO;


namespace wavHeaderParser
{
    class wavHeaderReader
    {

        string FilenameWithPath = "C:\\src\\test.wav";
        byte[] mheader = new byte[4] { 82, 73, 70, 70 }; /* 0 - 4 Bytes */
        UInt32 riffIDSize = 0;          /* 4 - 7 Bytes */
        byte[] wave = new byte[4] { 87, 65, 86, 69 }; /* 8 - 11 Bytes */
        byte[] fmt = new byte[4] { 102, 109, 116, 32 }; /* 12 - 15 Bytes */
        UInt32 Subchunk1Size = 0;
        UInt16 AudioFormat = 0;
        UInt16 NumOfChan = 0;
        UInt32 SamplesPerSec = 0;
        UInt32 bytesPerSec = 0;
        UInt16 blockAlign = 0;
        UInt16 bitsPerSample = 0;
        byte[] Subchunk2ID = new byte[4]{100,97,116,97};
        UInt32 Subchunk2Size = 0;
        byte[] wavHeaderBytes = new byte[44];

        byte[] ReadWavHeaderBytes(string FilenamewithPath)
        {
            const int wavHeaderSizeinBytes = 44;
            byte[] wavHeaderBytes = new byte[wavHeaderSizeinBytes];
            FileStream fs = new FileStream(FilenamewithPath, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);
            wavHeaderBytes = br.ReadBytes(wavHeaderSizeinBytes);
            return wavHeaderBytes;
        }
        public void getWavHeaderData()
        {
            wavHeaderBytes = ReadWavHeaderBytes(FilenameWithPath);
            Console.WriteLine("----------------------------------------------");
            Console.WriteLine(" WAV Header information:");
            Console.WriteLine("----------------------------------------------");
            if ((wavHeaderBytes[0] == mheader[0]) && (wavHeaderBytes[1] == mheader[1]) && (wavHeaderBytes[2] == mheader[2]) && (wavHeaderBytes[3] == mheader[3]))
            {
                Console.WriteLine(" Magic Header Found : {0}{1}{2}{3} ", (char)wavHeaderBytes[0], (char)wavHeaderBytes[1], (char)wavHeaderBytes[2], (char)wavHeaderBytes[3]);
            }

            riffIDSize = (UInt32)(wavHeaderBytes[7] << 24 | wavHeaderBytes[6] << 16 | wavHeaderBytes[5] << 8 | wavHeaderBytes[4]);
 
            if ((wavHeaderBytes[8] == wave[0]) && (wavHeaderBytes[9] == wave[1]) && (wavHeaderBytes[10] == wave[2]) && (wavHeaderBytes[11] == wave[3]))
            {
                Console.WriteLine(" wave Header Found  : {0}{1}{2}{3} ", (char)wavHeaderBytes[8], (char)wavHeaderBytes[9], (char)wavHeaderBytes[10], (char)wavHeaderBytes[11]);
            }
            if ((wavHeaderBytes[12] == fmt[0]) && (wavHeaderBytes[13] == fmt[1]) && (wavHeaderBytes[14] == fmt[2]) && (wavHeaderBytes[15] == fmt[3]))
            {
                Console.WriteLine(" fmt Header Found   : {0}{1}{2}{3} ", (char)wavHeaderBytes[12], (char)wavHeaderBytes[13], (char)wavHeaderBytes[14], (char)wavHeaderBytes[15]);
            }
            Subchunk1Size = (UInt32)(wavHeaderBytes[19] << 24 | wavHeaderBytes[18] << 16 | wavHeaderBytes[17] << 8 | wavHeaderBytes[16]);
            AudioFormat   = (UInt16)(wavHeaderBytes[21] << 8 | wavHeaderBytes[20]);
            NumOfChan     = (UInt16)(wavHeaderBytes[23] << 8 | wavHeaderBytes[22]);
            SamplesPerSec = (UInt32)(wavHeaderBytes[27] << 24 | wavHeaderBytes[26] << 16 | wavHeaderBytes[25] << 8 | wavHeaderBytes[24]);
            bytesPerSec   = (UInt32)(wavHeaderBytes[31] << 24 | wavHeaderBytes[30] << 16 | wavHeaderBytes[29] << 8 | wavHeaderBytes[28]);
            blockAlign    = (UInt16)(wavHeaderBytes[33] << 8 | wavHeaderBytes[32]);
            bitsPerSample = (UInt16)(wavHeaderBytes[35] << 8 | wavHeaderBytes[34]);
            Console.WriteLine(" RiffIDSize         : {0}",riffIDSize);
            Console.WriteLine(" Subchunk1Size      : {0}",Subchunk1Size);
            Console.WriteLine(" AudioFormat        : {0}",AudioFormat);
            Console.WriteLine(" NumOfChan          : {0}",NumOfChan);
            Console.WriteLine(" SamplesPerSec      : {0}",SamplesPerSec);
            Console.WriteLine(" bytesPerSec        : {0}", bytesPerSec);
            Console.WriteLine(" blockAlign         : {0}", blockAlign);
            Console.WriteLine(" bitsPerSample      : {0}", bitsPerSample);
            if ((wavHeaderBytes[36] == Subchunk2ID[0]) && (wavHeaderBytes[37] == Subchunk2ID[1]) && (wavHeaderBytes[38] == Subchunk2ID[2]) && (wavHeaderBytes[39] == Subchunk2ID[3]))
            {
                Console.WriteLine(" data Header Found  : {0}{1}{2}{3} ", (char)wavHeaderBytes[36],(char)wavHeaderBytes[37],(char)wavHeaderBytes[38],(char)wavHeaderBytes[39]);
            }
            Subchunk2Size = (UInt32)(wavHeaderBytes[43] << 24 | wavHeaderBytes[42] << 16 | wavHeaderBytes[41] << 8 | wavHeaderBytes[40]);
            Console.WriteLine(" Subchunk2Size      : {0}", Subchunk2Size);
            Console.WriteLine("----------------------------------------------");
            Console.ReadLine();
        }

    }
}

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)));
}