mulaw-conversion.c 3.68 KB
Newer Older
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * This routine converts from linear to ulaw
 * 29 September 1989
 *
 * Craig Reese: IDA/Supercomputing Research Center
 * Joe Campbell: Department of Defense
 *
 * References:
 * 1) CCITT Recommendation G.711  (very difficult to follow)
 * 2) "A New Digital Technique for Implementation of Any 
 *     Continuous PCM Companding Law," Villeret, Michel,
 *     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
 *     1973, pg. 11.12-11.17
 * 3) MIL-STD-188-113,"Interoperability and Performance Standards
 *     for Analog-to_Digital Conversion Techniques,"
 *     17 February 1987
 *
 * Input: Signed 16 bit linear sample
 * Output: 8 bit ulaw sample
 */

22 23 24 25
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
26 27
#include <glib.h>

28 29
#include "mulaw-conversion.h"

30
#undef ZEROTRAP                 /* turn on the trap as per the MIL-STD */
31
#define BIAS 0x84               /* define the add-in bias for 16 bit samples */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
32 33 34
#define CLIP 32635

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
35
mulaw_encode (gint16 * in, guint8 * out, gint numsamples)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
36
{
37 38
  static const gint16 exp_lut[256] = {
    0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
  };
55
  gint16 sign, exponent, mantissa;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
56 57
  gint16 sample;
  guint8 ulawbyte;
58
  gint i;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
59

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
60 61
  for (i = 0; i < numsamples; i++) {
    sample = in[i];
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
62
      /** get the sample into sign-magnitude **/
63
    sign = (sample >> 8) & 0x80;        /* set aside the sign */
64
    if (sign != 0) {
65
      sample = -sample;         /* get magnitude */
66 67 68 69
    }
    /* sample can be zero because we can overflow in the inversion,
     * checking against the unsigned version solves this */
    if (((guint16) sample) > CLIP)
70
      sample = CLIP;            /* clip the magnitude */
71

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
72
      /** convert from 16 bit linear to ulaw **/
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73 74 75 76
    sample = sample + BIAS;
    exponent = exp_lut[(sample >> 7) & 0xFF];
    mantissa = (sample >> (exponent + 3)) & 0x0F;
    ulawbyte = ~(sign | (exponent << 4) | mantissa);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
77
#ifdef ZEROTRAP
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
78
    if (ulawbyte == 0)
79
      ulawbyte = 0x02;          /* optional CCITT trap */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
80
#endif
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
81 82
    out[i] = ulawbyte;
  }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
}

/*
 * This routine converts from ulaw to 16 bit linear
 * 29 September 1989
 *
 * Craig Reese: IDA/Supercomputing Research Center
 *
 * References:
 * 1) CCITT Recommendation G.711  (very difficult to follow)
 * 2) MIL-STD-188-113,"Interoperability and Performance Standards
 *     for Analog-to_Digital Conversion Techniques,"
 *     17 February 1987
 *
 * Input: 8 bit ulaw sample
 * Output: signed 16 bit linear sample
 */

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
102
mulaw_decode (guint8 * in, gint16 * out, gint numsamples)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
103
{
104 105
  static const gint16 exp_lut[8] =
      { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
106 107
  gint16 sign, exponent, mantissa;
  guint8 ulawbyte;
108 109
  gint16 linear;
  gint i;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
110 111 112 113 114 115 116 117 118 119 120 121

  for (i = 0; i < numsamples; i++) {
    ulawbyte = in[i];
    ulawbyte = ~ulawbyte;
    sign = (ulawbyte & 0x80);
    exponent = (ulawbyte >> 4) & 0x07;
    mantissa = ulawbyte & 0x0F;
    linear = exp_lut[exponent] + (mantissa << (exponent + 3));
    if (sign != 0)
      linear = -linear;
    out[i] = linear;
  }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
122
}