alaw_ulaw.h

Go to the documentation of this file.
00001 /*
00002  * SpanDSP - a series of DSP components for telephony
00003  *
00004  * alaw_ulaw.h - In line A-law and u-law conversion routines
00005  *
00006  * Written by Steve Underwood <steveu@coppice.org>
00007  *
00008  * Copyright (C) 2001 Steve Underwood
00009  *
00010  * All rights reserved.
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025  *
00026  * $Id: alaw_ulaw.h,v 1.13 2006/01/18 13:21:37 steveu Exp $
00027  */
00028 
00029 /*! \file */
00030 
00031 /*! \page alaw_ulaw_page A-law and mu-law handling
00032 Lookup tables for A-law and u-law look attractive, until you consider the impact
00033 on the CPU cache. If it causes a substantial area of your processor cache to get
00034 hit too often, cache sloshing will severely slow things down. The main reason
00035 these routines are slow in C, is the lack of direct access to the CPU's "find
00036 the first 1" instruction. A little in-line assembler fixes that, and the
00037 conversion routines can be faster than lookup tables, in most real world usage.
00038 A "find the first 1" instruction is available on most modern CPUs, and is a
00039 much underused feature. 
00040 
00041 If an assembly language method of bit searching is not available, these routines
00042 revert to a method that can be a little slow, so the cache thrashing might not
00043 seem so bad :(
00044 
00045 Feel free to submit patches to add fast "find the first 1" support for your own
00046 favourite processor.
00047 */
00048 
00049 #if !defined(_ALAW_ULAW_H_)
00050 #define _ALAW_ULAW_H_
00051 
00052 #ifdef __cplusplus
00053 extern "C" {
00054 #endif
00055 
00056 #if defined(__i386__)
00057 static __inline__ int top_bit(unsigned int bits)
00058 {
00059     int res;
00060 
00061     __asm__ __volatile__(" movl $-1,%%edx;\n"
00062                          " bsrl %%eax,%%edx;\n"
00063                          : "=d" (res)
00064                          : "a" (bits));
00065     return res;
00066 }
00067 /*- End of function --------------------------------------------------------*/
00068 
00069 static __inline__ int bottom_bit(unsigned int bits)
00070 {
00071     int res;
00072 
00073     __asm__ __volatile__(" movl $-1,%%edx;\n"
00074                          " bsfl %%eax,%%edx;\n"
00075                          : "=d" (res)
00076                          : "a" (bits));
00077     return res;
00078 }
00079 /*- End of function --------------------------------------------------------*/
00080 #elif defined(__x86_64__)
00081 static __inline__ int top_bit(unsigned int bits)
00082 {
00083     int res;
00084 
00085     __asm__ __volatile__(" movq $-1,%%rdx;\n"
00086                          " bsrq %%rax,%%rdx;\n"
00087                          : "=d" (res)
00088                          : "a" (bits));
00089     return res;
00090 }
00091 /*- End of function --------------------------------------------------------*/
00092 
00093 static __inline__ int bottom_bit(unsigned int bits)
00094 {
00095     int res;
00096 
00097     __asm__ __volatile__(" movq $-1,%%rdx;\n"
00098                          " bsfq %%eax,%%edx;\n"
00099                          : "=d" (res)
00100                          : "a" (bits));
00101     return res;
00102 }
00103 /*- End of function --------------------------------------------------------*/
00104 #else
00105 static __inline__ int top_bit(unsigned int bits)
00106 {
00107     int i;
00108     
00109     if (bits == 0)
00110         return -1;
00111     i = 0;
00112     if (bits & 0xFFFF0000)
00113     {
00114         bits &= 0xFFFF0000;
00115         i += 16;
00116     }
00117     if (bits & 0xFF00FF00)
00118     {
00119         bits &= 0xFF00FF00;
00120         i += 8;
00121     }
00122     if (bits & 0xF0F0F0F0)
00123     {
00124         bits &= 0xF0F0F0F0;
00125         i += 4;
00126     }
00127     if (bits & 0xCCCCCCCC)
00128     {
00129         bits &= 0xCCCCCCCC;
00130         i += 2;
00131     }
00132     if (bits & 0xAAAAAAAA)
00133     {
00134         bits &= 0xAAAAAAAA;
00135         i += 1;
00136     }
00137     return i;
00138 }
00139 /*- End of function --------------------------------------------------------*/
00140 
00141 static __inline__ int bottom_bit(unsigned int bits)
00142 {
00143     int i;
00144     
00145     if (bits == 0)
00146         return -1;
00147     i = 32;
00148     if (bits & 0x0000FFFF)
00149     {
00150         bits &= 0x0000FFFF;
00151         i -= 16;
00152     }
00153     if (bits & 0x00FF00FF)
00154     {
00155         bits &= 0x00FF00FF;
00156         i -= 8;
00157     }
00158     if (bits & 0x0F0F0F0F)
00159     {
00160         bits &= 0x0F0F0F0F;
00161         i -= 4;
00162     }
00163     if (bits & 0x33333333)
00164     {
00165         bits &= 0x33333333;
00166         i -= 2;
00167     }
00168     if (bits & 0x55555555)
00169     {
00170         bits &= 0x55555555;
00171         i -= 1;
00172     }
00173     return i;
00174 }
00175 /*- End of function --------------------------------------------------------*/
00176 #endif
00177 
00178 /* N.B. It is tempting to use look-up tables for A-law and u-law conversion.
00179  *      However, you should consider the cache footprint.
00180  *
00181  *      A 64K byte table for linear to x-law and a 512 byte sound like peanuts
00182  *      these days, and shouldn't an array lookup be real fast? No! When the
00183  *      cache sloshes as badly as this one will, a tight calculation is better.
00184  *      The messiest part is normally finding the segment, but a little inline
00185  *      assembly can fix that on an i386.
00186  */
00187  
00188 /*
00189  * Mu-law is basically as follows:
00190  *
00191  *      Biased Linear Input Code        Compressed Code
00192  *      ------------------------        ---------------
00193  *      00000001wxyza                   000wxyz
00194  *      0000001wxyzab                   001wxyz
00195  *      000001wxyzabc                   010wxyz
00196  *      00001wxyzabcd                   011wxyz
00197  *      0001wxyzabcde                   100wxyz
00198  *      001wxyzabcdef                   101wxyz
00199  *      01wxyzabcdefg                   110wxyz
00200  *      1wxyzabcdefgh                   111wxyz
00201  *
00202  * Each biased linear code has a leading 1 which identifies the segment
00203  * number. The value of the segment number is equal to 7 minus the number
00204  * of leading 0's. The quantization interval is directly available as the
00205  * four bits wxyz.  * The trailing bits (a - h) are ignored.
00206  *
00207  * Ordinarily the complement of the resulting code word is used for
00208  * transmission, and so the code word is complemented before it is returned.
00209  *
00210  * For further information see John C. Bellamy's Digital Telephony, 1982,
00211  * John Wiley & Sons, pps 98-111 and 472-476.
00212  */
00213 
00214 //#define ZEROTRAP                      /* turn on the trap as per the MIL-STD */
00215 #define BIAS             0x84           /* Bias for linear code. */
00216 
00217 static __inline__ uint8_t linear_to_ulaw(int linear)
00218 {
00219     uint8_t u_val;
00220     int mask;
00221     int seg;
00222 
00223     /* Get the sign and the magnitude of the value. */
00224     if (linear < 0)
00225     {
00226         linear = BIAS - linear;
00227         mask = 0x7F;
00228     }
00229     else
00230     {
00231         linear = BIAS + linear;
00232         mask = 0xFF;
00233     }
00234 
00235     seg = top_bit(linear | 0xFF) - 7;
00236 
00237     /*
00238      * Combine the sign, segment, quantization bits,
00239      * and complement the code word.
00240      */
00241     if (seg >= 8)
00242         u_val = 0x7F ^ mask;
00243     else
00244         u_val = ((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask;
00245 #ifdef ZEROTRAP
00246     /* optional ITU trap */
00247     if (u_val == 0)
00248         u_val = 0x02;
00249 #endif
00250     return  u_val;
00251 }
00252 /*- End of function --------------------------------------------------------*/
00253 
00254 static __inline__ int16_t ulaw_to_linear(uint8_t ulaw)
00255 {
00256     int t;
00257     
00258     /* Complement to obtain normal u-law value. */
00259     ulaw = ~ulaw;
00260     /*
00261      * Extract and bias the quantization bits. Then
00262      * shift up by the segment number and subtract out the bias.
00263      */
00264     t = (((ulaw & 0x0F) << 3) + BIAS) << (((int) ulaw & 0x70) >> 4);
00265     return  ((ulaw & 0x80)  ?  (BIAS - t) : (t - BIAS));
00266 }
00267 /*- End of function --------------------------------------------------------*/
00268 
00269 /*
00270  * A-law is basically as follows:
00271  *
00272  *      Linear Input Code        Compressed Code
00273  *      -----------------        ---------------
00274  *      0000000wxyza             000wxyz
00275  *      0000001wxyza             001wxyz
00276  *      000001wxyzab             010wxyz
00277  *      00001wxyzabc             011wxyz
00278  *      0001wxyzabcd             100wxyz
00279  *      001wxyzabcde             101wxyz
00280  *      01wxyzabcdef             110wxyz
00281  *      1wxyzabcdefg             111wxyz
00282  *
00283  * For further information see John C. Bellamy's Digital Telephony, 1982,
00284  * John Wiley & Sons, pps 98-111 and 472-476.
00285  */
00286 
00287 #define AMI_MASK        0x55
00288 
00289 static __inline__ uint8_t linear_to_alaw(int linear)
00290 {
00291     int mask;
00292     int seg;
00293     
00294     if (linear >= 0)
00295     {
00296         /* Sign (7th) bit = 1 */
00297         mask = AMI_MASK | 0x80;
00298     }
00299     else
00300     {
00301         /* Sign (7th) bit = 0 */
00302         mask = AMI_MASK;
00303         linear = -linear - 8;
00304     }
00305 
00306     /* Convert the scaled magnitude to segment number. */
00307     seg = top_bit(linear | 0xFF) - 7;
00308     if (seg >= 8)
00309     {
00310         if (linear >= 0)
00311         {
00312             /* Out of range. Return maximum value. */
00313             return (0x7F ^ mask);
00314         }
00315         /* We must be just a tiny step below zero */
00316         return (0x00 ^ mask);
00317     }
00318     /* Combine the sign, segment, and quantization bits. */
00319     return  ((seg << 4) | ((linear >> ((seg)  ?  (seg + 3)  :  4)) & 0x0F)) ^ mask;
00320 }
00321 /*- End of function --------------------------------------------------------*/
00322 
00323 static __inline__ int16_t alaw_to_linear(uint8_t alaw)
00324 {
00325     int i;
00326     int seg;
00327 
00328     alaw ^= AMI_MASK;
00329     i = ((alaw & 0x0F) << 4);
00330     seg = (((int) alaw & 0x70) >> 4);
00331     if (seg)
00332         i = (i + 0x108) << (seg - 1);
00333     else
00334         i += 8;
00335     return (int16_t) ((alaw & 0x80)  ?  i  :  -i);
00336 }
00337 /*- End of function --------------------------------------------------------*/
00338 
00339 #ifdef __cplusplus
00340 }
00341 #endif
00342 
00343 #endif
00344 /*- End of file ------------------------------------------------------------*/

Generated on Fri Nov 10 09:40:23 2006 for libspandsp by  doxygen 1.5.1