Thu Apr 28 2011 16:56:49

Asterisk developer's documentation


ulaw.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief u-Law to Signed linear conversion
00022  *
00023  * \author Mark Spencer <markster@digium.com> 
00024  */
00025 
00026 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 213182 $")
00029 
00030 #include "asterisk/ulaw.h"
00031 #include "asterisk/logger.h"
00032 
00033 #if 0
00034 /* ZEROTRAP is the military recommendation to improve the encryption
00035  * of u-Law traffic. It is irrelevant with modern encryption systems
00036  * like AES, and will simply degrade the signal quality.
00037  * ZEROTRAP is not implemented in AST_LIN2MU and so the coding table
00038  * tests will fail if you use it */
00039 #define ZEROTRAP    /*!< turn on the trap as per the MIL-STD */
00040 #endif
00041 
00042 #define BIAS 0x84   /*!< define the add-in bias for 16 bit samples */
00043 #define CLIP 32635
00044 
00045 #ifndef G711_NEW_ALGORITHM
00046 
00047 unsigned char __ast_lin2mu[16384];
00048 short __ast_mulaw[256];
00049 
00050 static unsigned char linear2ulaw(short sample)
00051 {
00052    static int exp_lut[256] = {
00053       0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00054       4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00055       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00056       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00057       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00058       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00059       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00060       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00061       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00062       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00063       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00064       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00065       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00066       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00067       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00068       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
00069    int sign, exponent, mantissa;
00070    unsigned char ulawbyte;
00071    
00072    /* Get the sample into sign-magnitude. */
00073    sign = (sample >> 8) & 0x80;          /* set aside the sign */
00074    if (sign != 0)
00075       sample = -sample;              /* get magnitude */
00076    if (sample > CLIP)
00077       sample = CLIP;             /* clip the magnitude */
00078    
00079    /* Convert from 16 bit linear to ulaw. */
00080    sample = sample + BIAS;
00081    exponent = exp_lut[(sample >> 7) & 0xFF];
00082    mantissa = (sample >> (exponent + 3)) & 0x0F;
00083    ulawbyte = ~(sign | (exponent << 4) | mantissa);
00084    
00085 #ifdef ZEROTRAP
00086    if (ulawbyte == 0)
00087       ulawbyte = 0x02;   /* optional CCITT trap */
00088 #endif
00089    
00090    return ulawbyte;
00091 }
00092 
00093 #else
00094 
00095 unsigned char __ast_lin2mu[AST_ULAW_TAB_SIZE];
00096 short __ast_mulaw[256];
00097 
00098 static unsigned char linear2ulaw(short sample, int full_coding)
00099 {
00100    static const unsigned exp_lut[256] = {
00101       0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00102       4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00103       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00104       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00105       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00106       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00107       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00108       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00109       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00110       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00111       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00112       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00113       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00114       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00115       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00116       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
00117    unsigned sign, exponent, mantissa, mag;
00118    unsigned char ulawbyte;
00119    
00120    /* Get the sample into sign-magnitude. */
00121    ast_ulaw_get_sign_mag(sample, &sign, &mag);
00122    if (mag > CLIP)
00123       mag = CLIP;                /* clip the magnitude */
00124    
00125    sign = (sample >> 8) & 0x80;          /* set aside the sign */
00126    if (sign != 0) 
00127       sample = -sample;              /* get magnitude */
00128    if (sample > CLIP)
00129       sample = CLIP;             /* clip the magnitude */
00130    
00131    /* Convert from 16 bit linear to ulaw. */
00132    mag += BIAS;
00133    exponent = exp_lut[(mag >> 7) & 0xFF];
00134    mantissa = (mag >> (exponent + 3)) & 0x0F;
00135    
00136    if (full_coding) {
00137       /* full encoding, with sign and xform */
00138       ulawbyte = ~(sign | (exponent << 4) | mantissa);
00139 #ifdef ZEROTRAP
00140       if (ulawbyte == 0)
00141          ulawbyte = 0x02;   /* optional CCITT trap */
00142 #endif
00143    } else {
00144       /* half-cooked coding -- mantissa+exponent only (for lookup tab) */
00145       ulawbyte = (exponent << 4) | mantissa;
00146    }
00147 
00148    return ulawbyte;
00149 }
00150    
00151 static inline short ulaw2linear(unsigned char ulawbyte)
00152 {
00153    unsigned exponent, mantissa;
00154    short sample;
00155    static const short etab[]={0,132,396,924,1980,4092,8316,16764};
00156    
00157    ulawbyte = ~ulawbyte;
00158    exponent = (ulawbyte & 0x70) >> 4;
00159    mantissa = ulawbyte & 0x0f;
00160    sample = mantissa << (exponent + 3);
00161    sample += etab[exponent];
00162    if (ulawbyte & 0x80)
00163       sample = -sample;
00164    return sample;
00165 }
00166 #endif
00167 
00168 /*!
00169  * \brief  Set up mu-law conversion table
00170  */
00171 void ast_ulaw_init(void)
00172 {
00173    int i;
00174    
00175    /*
00176     *  Set up mu-law conversion table
00177     */
00178 #ifndef G711_NEW_ALGORITHM
00179    for (i = 0;i < 256;i++) {
00180       short mu,e,f,y;
00181       static short etab[]={0,132,396,924,1980,4092,8316,16764};
00182       
00183       mu = 255-i;
00184       e = (mu & 0x70)/16;
00185       f = mu & 0x0f;
00186       y = f * (1 << (e + 3));
00187       y += etab[e];
00188       if (mu & 0x80) y = -y;
00189       __ast_mulaw[i] = y;
00190    }
00191    /* set up the reverse (mu-law) conversion table */
00192    for (i = -32768; i < 32768; i++) {
00193       __ast_lin2mu[((unsigned short)i) >> 2] = linear2ulaw(i);
00194    }
00195 #else
00196    
00197    for (i = 0; i < 256; i++) {
00198       __ast_mulaw[i] = ulaw2linear(i);
00199    }
00200    /* set up the reverse (mu-law) conversion table */
00201    for (i = 0; i <= 32768; i += AST_ULAW_STEP) {
00202       AST_LIN2MU_LOOKUP(i) = linear2ulaw(i, 0 /* half-cooked */);
00203    }
00204 #endif
00205    
00206 #ifdef TEST_CODING_TABLES
00207    for (i = -32768; i < 32768; ++i) {
00208 #ifndef G711_NEW_ALGORITHM
00209       unsigned char e1 = linear2ulaw(i);
00210 #else
00211       unsigned char e1 = linear2ulaw(i, 1);
00212 #endif
00213       short d1 = ulaw2linear(e1);
00214       unsigned char e2 = AST_LIN2MU(i);
00215       short d2 = ulaw2linear(e2);
00216       short d3 = AST_MULAW(e1);
00217       
00218       if (e1 != e2 || d1 != d3 || d2 != d3) {
00219          ast_log(LOG_WARNING, "u-Law coding tables test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d\n",
00220                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2);
00221       }
00222    }
00223    ast_log(LOG_NOTICE, "u-Law coding table test complete.\n");
00224 #endif /* TEST_CODING_TABLES */
00225    
00226 #ifdef TEST_TANDEM_TRANSCODING
00227    /* tandem transcoding test */
00228    for (i = -32768; i < 32768; ++i) {
00229       unsigned char e1 = AST_LIN2MU(i);
00230       short d1 = AST_MULAW(e1);
00231       unsigned char e2 = AST_LIN2MU(d1);
00232       short d2 = AST_MULAW(e2);
00233       unsigned char e3 = AST_LIN2MU(d2);
00234       short d3 = AST_MULAW(e3);
00235       
00236       if (i < 0 && e1 == 0x7f && e2 == 0xff && e3 == 0xff)
00237          continue; /* known and normal negative 0 case */
00238       
00239       if (e1 != e2 || e2 != e3 || d1 != d2 || d2 != d3) {
00240          ast_log(LOG_WARNING, "u-Law tandem transcoding test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d, d3=%d\n",
00241                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2, (int)d3);
00242       }
00243    }
00244    ast_log(LOG_NOTICE, "u-Law tandem transcoding test complete.\n");
00245 #endif /* TEST_TANDEM_TRANSCODING */
00246 }
00247