/*
=============================================================================

                          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".
       =============================================================
*/

/******************************************************************************
**
**  Filename:     g711_encoder.c
**
**  System:       RISC
**
**  Platform:     dsPIC33F
**
**  Description:  This file contains g711 Alaw and ulaw compress functions.
**
******************************************************************************/

#include "g711.h"

/******************************************************************************
**
**  FunctionName: alaw_compress ( )
**
**  Description:  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.
******************************************************************************/
void  alaw_compress(long lseg, short* linbuf, unsigned char* 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 ulaw_compress() ..................... */
/******************************************************************************
**
**  FunctionName: ulaw_compress ( )
**
**  Description:  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.
******************************************************************************/
void ulaw_compress(long lseg, short* linbuf, unsigned char* 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() ..................... */



/*-----------------------------------------------------------------------------
                      END OF FILE:  g711_encoder.c
-----------------------------------------------------------------------------*/


