Logo Search packages:      
Sourcecode: vat version File versions

mktab.c

/*
 * Copyright (c) 1991 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Lawrence Berkeley Laboratory,
 * Berkeley, CA.  The name of the University may not be used to
 * endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
static const char rcsid[] =
    "@(#) $Header: mktab.c,v 1.5 96/03/18 00:52:01 van Exp $ (LBL)";

#include "config.h"
#include <stdio.h>
#include <math.h>
#include "mulaw.h"

#define BIAS 0x84
#define CLIP 32635

u_int8_t
st_linear_to_ulaw(register int linear)
{
      static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
                           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};
      register int sign, exponent, mantissa;
      register u_int8_t ulawbyte;
      
      /* Get the value into sign-magnitude. */
      sign = (linear >> 8) & 0x80;
      if (sign != 0) {
            /* sign extend the value, just in case */
            linear |= 0xffff0000;
            linear = -linear;
      }
      if (linear > CLIP)
            linear = CLIP;
      
      /* Convert from 16 bit linear to ulaw. */
      linear += BIAS;
      exponent = exp_lut[(linear >> 7) & 0xFF];
      mantissa = (linear >> (exponent + 3)) & 0x0F;
      ulawbyte = ~(sign | (exponent << 4) | mantissa);
      return ulawbyte;
}

int
st_ulaw_to_linear(u_int8_t ulawbyte)
{
      static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
      int sign, exponent, mantissa, sample;
      
      ulawbyte = ~ulawbyte;
      sign = (ulawbyte & 0x80);
      exponent = (ulawbyte >> 4) & 0x07;
      mantissa = ulawbyte & 0x0F;
      sample = exp_lut[exponent] + (mantissa << (exponent + 3)) +
             (1 << (exponent + 2));
      if (sign != 0)
            sample = -sample;
      /*
       * ulaw maps zero to full-scale negative.  This is a very poor
       * choice given that most i/o failure modes stick zero in the
       * buffer.  So, to save our ears, we map ulaw zero to linear zero.
       */
      return (ulawbyte == 0xff? 0 : sample);
}

void
tab_tolin(register FILE *f)
{
      register int i, j;

      fprintf(f, "const int16_t mulawtolin[256] = {\n");
      for (i = 0; i < 256; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", st_ulaw_to_linear(i));
            putc('\n', f);
      }
      fprintf(f, "};\n");
}

void
tab_tomu(register FILE *f)
{
      register int i, j;

      fprintf(f, "const u_int8_t lintomulaw[65536] = {\n");
      for (i = 0; i < 65536; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", st_linear_to_ulaw(i));
            putc('\n', f);
      }
      fprintf(f, "};\n");
}

/*
 * build a linear to mulaw lookup table extended by 1
 * bit to handle clipping in the table lookup rather
 * than testing each sample.
 */
void
tab_tomuX(register FILE *f)
{
      register int i, j;

      fprintf(f, "const u_int8_t lintomulawX[65536*2] = {\n");
      /* positive half */
      for (i = 0; i < 32768; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", st_linear_to_ulaw(i));
            putc('\n', f);
      }
      /* positive overflow (clipped) */
      for (i = 32768; i < 65536; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", 0x80);
            putc('\n', f);
      }
      /* negative overflow (clipped) */
      for (i = 65536; i < 98304; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", 0x01);
            putc('\n', f);
      }
      /* negative half */
      for (i = 98304; i < 131072; ) {
            putc('\t', f);
            for (j = i + 8; i < j; ++i) 
                  fprintf(f, "%d, ", st_linear_to_ulaw(i));
            putc('\n', f);
      }
      fprintf(f, "};\n");
}

void
prtone(register FILE *f, register int u)
{
      if (u < -CLIP)
            u = -CLIP;
      else if (u > CLIP)
            u = CLIP;
      fprintf(f, "%d, ", st_linear_to_ulaw(u));
}

void
tab_sum(register FILE *f)
{
      register int i, j, k, u;

      fprintf(f, "const u_int8_t mulawsum[256*256] = {\n");
      for (i = 0; i < 256; ++i) {
            fprintf(f, "/* %d */\n", i);
            u = st_ulaw_to_linear(i);
            for (j = 0; j < 256; ) {
                  putc('\t', f);
                  for (k = j + 8; j < k; ++j)
                        prtone(f, u + st_ulaw_to_linear(j));
                  putc('\n', f);
            }
      }
      fprintf(f, "};\n");
}

void
prt8(register FILE *f, register int u, register int* us)
{
      register int k;

      putc('\t', f);
      for (k = 0; k < 8; ++k)
            prtone(f, u + us[k]);
      putc('\n', f);
}

void
prtup64(register FILE *f, register int u, register int uj)
{
      register int k;
      int us[64], uabs, uk;

      /*
       * compute the 64 values that would precede uj in a mulaw
       * table (assuming a gain of 17/16 which is roughly right
       * for large uj).  Do them in reverse order since mulaw
       * values are complemented.
       */
      uabs = (uj>=0? uj : -uj) << 4;
      for (k = 64; --k >= 0; ) {
            uk = uabs >> 4;
            us[k] = uj>=0? uk : -uk;
            uabs += uk;
      }
      for (k = 0; k < 64; k += 8)
            prt8(f, u, us + k);
}

void
prtlow64(register FILE *f, register int u, register int uj)
{
      register int k;
      int us[64], uabs, uk;

      /*
       * compute the 64 values that would follow uj in a mulaw
       * table.
       */
      uabs = 1 << 4;
      for (k = 48; --k >= 0; ) {
            uk = uabs >> 4;
            us[k] = uj>=0? uk : -uk;
            uabs += uk;
      }
      for (k = 64; --k >= 48; ) {
            us[k] = 0;
      }
      for (k = 0; k < 64; k += 8)
            prt8(f, u, us + k);
}

void
tab_mugain(register FILE *f)
{
      register int i, j, k;
#define M 16.
      double g = 1.;
      double gi = pow(M, (double)1. / 32.);

      fprintf(f, "const u_int8_t mugaintab[64*256] = {\n");
      for (i = 0; i < 64; ++i) {
            fprintf(f, "/* step %d (gain %g) */\n", i - 32, g / M);

            for (j = 0; j < 256; ) {
                  putc('\t', f);
                  for (k = j + 8; j < k; ++j) {
                        double v = g / M * (double)st_ulaw_to_linear(j);
                        prtone(f, (int)v);
                  }
                  putc('\n', f);
            }
            g *= gi;
      }
      fprintf(f, "};\n");
#undef M
}

/*
 * Output a table that maps mulaw samples to power levels, where
 * the power level is given by p = log_2(x^2) (i.e., not really db).
 * p is expressed in 32-bit fixed point, with 19 bits of fraction.
 * Since ulaw samples range over 16 bits (linear), we need 32 bits
 * to represent log_2(x^2).  To compute the power in a frame, we add
 * 160 of these samples, so we need to be able to represent 32 * 160 = 0x1400,
 * with the encoding.  Thus, we need 13 bits for the integer part,
 * which gives 19 bits of fraction.  This encoding will allow the
 * frame size to go to 256.  Note that all the values are positive
 * since the smallest linear value is 4 (except for 0, which we will
 * just encode as 0).
 */
#ifdef notdef
tab_mudb(f)
      register FILE *f;
{
      register int i, j;
      double log2 = log((double)2);

      fprintf(f, "const unsigned long mulawtodb[256] = {\n");
      for (i = 0; i < 256; ) {
            putc('\t', f);
            for (j = i + 4; i < j; ++i) {
                  u_long s;
                  double d = (double)st_ulaw_to_linear(i);
                  if (d != 0) {
                        d = d * d;
                        d = log(d) / log2;
                        d *= (double)(1 << MUDB_FRACBITS);
                  }
                  fprintf(f, "0x%lx, ", (u_long)irint(d));
            }
            putc('\n', f);
      }
      fprintf(f, "};\n");
}

tab_x(f)
      register FILE *f;
{
      register int i;

      for (i = 0; i <= CLIP; ++i) {
            int u = st_linear_to_ulaw(i);
            printf("%d\n", ~u & 0x7f);
      }
}

tab_xx(f)
      register FILE *f;
{
      register int i;

      for (i = 0; i <= CLIP; ++i) {
            int u = st_linear_to_ulaw(i);
            printf("%d\n", st_ulaw_to_linear(u));
      }
}
#endif

int
main(int argc, char* argv[])
{
      if (argc != 2)
            exit(1);
      fprintf(stdout, "#include \"config.h\"\n");
      if (strcmp(argv[1], "-mulaw") == 0) {
            tab_tolin(stdout);
            tab_tomu(stdout);
      } else if (strcmp(argv[1], "-sum") == 0)
            tab_sum(stdout);
      else if (strcmp(argv[1], "-scale") == 0)
            tab_mugain(stdout);
      else if (strcmp(argv[1], "-muX") == 0)
            tab_tomuX(stdout);
#ifdef notdef
      else if (strcmp(argv[1], "-db") == 0)
            tab_mudb(stdout);
      else if (strcmp(argv[1], "-x") == 0)
            tab_x(stdout);
      else if (strcmp(argv[1], "-xx") == 0)
            tab_xx(stdout);
#endif
      else
            exit(1);
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index