Fri Jul 24 00:41:05 2009

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: 89425 $")
00029 
00030 #include "asterisk/ulaw.h"
00031 
00032 #if 0
00033 /* ZEROTRAP is the military recommendation to improve the encryption
00034  * of u-Law traffic. It is irrelevant with modern encryption systems
00035  * like AES, and will simply degrade the signal quality.
00036  * ZEROTRAP is not implemented in AST_LIN2MU and so the coding table
00037  * tests will fail if you use it */
00038 #define ZEROTRAP    /*!< turn on the trap as per the MIL-STD */
00039 #endif
00040 
00041 #define BIAS 0x84   /*!< define the add-in bias for 16 bit samples */
00042 #define CLIP 32635
00043 
00044 #ifndef G711_NEW_ALGORITHM
00045 
00046 unsigned char __ast_lin2mu[16384];
00047 short __ast_mulaw[256];
00048 
00049 static unsigned char linear2ulaw(short sample)
00050 {
00051    static int exp_lut[256] = {
00052       0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00053       4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00054       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00055       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00056       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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    int sign, exponent, mantissa;
00069    unsigned char ulawbyte;
00070    
00071    /* Get the sample into sign-magnitude. */
00072    sign = (sample >> 8) & 0x80;          /* set aside the sign */
00073    if (sign != 0)
00074       sample = -sample;              /* get magnitude */
00075    if (sample > CLIP)
00076       sample = CLIP;             /* clip the magnitude */
00077    
00078    /* Convert from 16 bit linear to ulaw. */
00079    sample = sample + BIAS;
00080    exponent = exp_lut[(sample >> 7) & 0xFF];
00081    mantissa = (sample >> (exponent + 3)) & 0x0F;
00082    ulawbyte = ~(sign | (exponent << 4) | mantissa);
00083    
00084 #ifdef ZEROTRAP
00085    if (ulawbyte == 0)
00086       ulawbyte = 0x02;   /* optional CCITT trap */
00087 #endif
00088    
00089    return ulawbyte;
00090 }
00091 
00092 #else
00093 
00094 unsigned char __ast_lin2mu[AST_ULAW_TAB_SIZE];
00095 short __ast_mulaw[256];
00096 
00097 static unsigned char linear2ulaw(short sample, int full_coding)
00098 {
00099    static const unsigned exp_lut[256] = {
00100       0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00101       4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00102       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00103       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00104       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
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    unsigned sign, exponent, mantissa, mag;
00117    unsigned char ulawbyte;
00118    
00119    /* Get the sample into sign-magnitude. */
00120    ast_ulaw_get_sign_mag(sample, &sign, &mag);
00121    if (mag > CLIP)
00122       mag = CLIP;                /* clip the magnitude */
00123    
00124    sign = (sample >> 8) & 0x80;          /* set aside the sign */
00125    if (sign != 0) 
00126       sample = -sample;              /* get magnitude */
00127    if (sample > CLIP)
00128       sample = CLIP;             /* clip the magnitude */
00129    
00130    /* Convert from 16 bit linear to ulaw. */
00131    mag += BIAS;
00132    exponent = exp_lut[(mag >> 7) & 0xFF];
00133    mantissa = (mag >> (exponent + 3)) & 0x0F;
00134    
00135    if (full_coding) {
00136       /* full encoding, with sign and xform */
00137       ulawbyte = ~(sign | (exponent << 4) | mantissa);
00138 #ifdef ZEROTRAP
00139       if (ulawbyte == 0)
00140          ulawbyte = 0x02;   /* optional CCITT trap */
00141 #endif
00142    } else {
00143       /* half-cooked coding -- mantissa+exponent only (for lookup tab) */
00144       ulawbyte = (exponent << 4) | mantissa;
00145    }
00146 
00147    return ulawbyte;
00148 }
00149    
00150 static inline short ulaw2linear(unsigned char ulawbyte)
00151 {
00152    unsigned exponent, mantissa;
00153    short sample;
00154    static const short etab[]={0,132,396,924,1980,4092,8316,16764};
00155    
00156    ulawbyte = ~ulawbyte;
00157    exponent = (ulawbyte & 0x70) >> 4;
00158    mantissa = ulawbyte & 0x0f;
00159    sample = mantissa << (exponent + 3);
00160    sample += etab[exponent];
00161    if (ulawbyte & 0x80)
00162       sample = -sample;
00163    return sample;
00164 }
00165 #endif
00166 
00167 /*!
00168  * \brief  Set up mu-law conversion table
00169  */
00170 void ast_ulaw_init(void)
00171 {
00172    int i;
00173    
00174    /*
00175     *  Set up mu-law conversion table
00176     */
00177 #ifndef G711_NEW_ALGORITHM
00178    for (i = 0;i < 256;i++) {
00179       short mu,e,f,y;
00180       static short etab[]={0,132,396,924,1980,4092,8316,16764};
00181       
00182       mu = 255-i;
00183       e = (mu & 0x70)/16;
00184       f = mu & 0x0f;
00185       y = f * (1 << (e + 3));
00186       y += etab[e];
00187       if (mu & 0x80) y = -y;
00188       __ast_mulaw[i] = y;
00189    }
00190    /* set up the reverse (mu-law) conversion table */
00191    for (i = -32768; i < 32768; i++) {
00192       __ast_lin2mu[((unsigned short)i) >> 2] = linear2ulaw(i);
00193    }
00194 #else
00195    
00196    for (i = 0; i < 256; i++) {
00197       __ast_mulaw[i] = ulaw2linear(i);
00198    }
00199    /* set up the reverse (mu-law) conversion table */
00200    for (i = 0; i <= 32768; i += AST_ULAW_STEP) {
00201       AST_LIN2MU_LOOKUP(i) = linear2ulaw(i, 0 /* half-cooked */);
00202    }
00203 #endif
00204    
00205 #ifdef TEST_CODING_TABLES
00206    for (i = -32768; i < 32768; ++i) {
00207 #ifndef G711_NEW_ALGORITHM
00208       unsigned char e1 = linear2ulaw(i);
00209 #else
00210       unsigned char e1 = linear2ulaw(i, 1);
00211 #endif
00212       short d1 = ulaw2linear(e1);
00213       unsigned char e2 = AST_LIN2MU(i);
00214       short d2 = ulaw2linear(e2);
00215       short d3 = AST_MULAW(e1);
00216       
00217       if (e1 != e2 || d1 != d3 || d2 != d3) {
00218          ast_log(LOG_WARNING, "u-Law coding tables test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d\n",
00219                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2);
00220       }
00221    }
00222    ast_log(LOG_NOTICE, "u-Law coding table test complete.\n");
00223 #endif /* TEST_CODING_TABLES */
00224    
00225 #ifdef TEST_TANDEM_TRANSCODING
00226    /* tandem transcoding test */
00227    for (i = -32768; i < 32768; ++i) {
00228       unsigned char e1 = AST_LIN2MU(i);
00229       short d1 = AST_MULAW(e1);
00230       unsigned char e2 = AST_LIN2MU(d1);
00231       short d2 = AST_MULAW(e2);
00232       unsigned char e3 = AST_LIN2MU(d2);
00233       short d3 = AST_MULAW(e3);
00234       
00235       if (i < 0 && e1 == 0x7f && e2 == 0xff && e3 == 0xff)
00236          continue; /* known and normal negative 0 case */
00237       
00238       if (e1 != e2 || e2 != e3 || d1 != d2 || d2 != d3) {
00239          ast_log(LOG_WARNING, "u-Law tandem transcoding test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d, d3=%d\n",
00240                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2, (int)d3);
00241       }
00242    }
00243    ast_log(LOG_NOTICE, "u-Law tandem transcoding test complete.\n");
00244 #endif /* TEST_TANDEM_TRANSCODING */
00245 }
00246 

Generated on Fri Jul 24 00:41:05 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7