/******************************************************************** * * * Voice Terminal (VT) * * June, 1991 * * * * Written at USC/Information Sciences Institute from an earlier * * version developed by Bolt Beranek and Newman Inc. * * * * Copyright (c) 1991 University of Southern 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 Southern California, Information * * Sciences Institute. 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR * * PURPOSE. * * * *******************************************************************/ /* Conversion between 8-bit mu-law and 14-bit linear PCM. For quick look-up, define a table. The macros should only be used if the domain of the argument is within permissible bounds. The routines are very similar to the ones by Craig Reese and Joe Campbell. */ // #include "types.h" /* u_int8 */ static char rcsid[] = "$Id: pcmu_l14.c,v 1.1 1995/01/19 19:18:39 hgs Exp $"; typedef short int16; typedef char int8; typedef unsigned char u_int8; int16 pcmu_l14_table[256]; u_int8 l8_pcmu_table[256]; u_int8 l14_pcmu_table[8192]; /* only positive side */ /* * Convert 8-bit mu-law value 'pcm' to 14-bit signed linear (-8031 .. 8031). */ int16 pcmu_to_l14(int pcm) { register unsigned int sign; /* save sign of PCM value */ register unsigned int segment; /* segment of piecewise linear curve (0..7) */ register unsigned int step; /* step along segment (0..15) */ register int16 lin; /* return linear value */ pcm = ~pcm & 0xFF; /* undo 1's complement of PCM */ sign = pcm & 0x80; /* extract sign bit */ pcm = pcm & 0x7F; /* retain only magnitude */ segment = pcm >> 4; /* separate into segment */ step = pcm & 0xF; /* and step within segment */ lin = ((2*step+33)< 8158) lin = 8158; /* Limit to maximum linear value */ lin += 33; /* Shift up against 8192 */ for (segment=7, decision=1<<(7+5); segment>=0; segment--, decision>>=1) if (decision < lin) break; /* Find first seg the value is above */ lin -= decision; /* Get offset from segment base */ step = lin / (decision>>4); /* Calculate step along segment */ return(~(sign + (segment<<4) + step) & 0xFF); /* Assemble PCM value */ } /* l14_to_pcmu */ /* * Initialize fast lookup tables for 8, 14, and 16 bit linear values. */ void pcmu_linear_init(void) { int u, l; for (u = 0; u < 256; u++) { pcmu_l14_table[u] = pcmu_to_l14(u); l8_pcmu_table[u] = l14_to_pcmu(u << 6); } for (l = 0; l < 8192; l++) l14_pcmu_table[l] = l14_to_pcmu(l); } /* pcmu_linear_init */