Wed Oct 28 11:50:51 2009

Asterisk developer's documentation


alaw.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 a-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: 213181 $")
00029 
00030 #include "asterisk/alaw.h"
00031 #include "asterisk/logger.h"
00032 
00033 #ifndef G711_NEW_ALGORITHM
00034 #define AMI_MASK 0x55
00035 
00036 static inline unsigned char linear2alaw(short int linear)
00037 {
00038    int mask;
00039    int seg;
00040    int pcm_val;
00041    static int seg_end[8] =
00042       {
00043          0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
00044       };
00045 
00046    pcm_val = linear;
00047    if (pcm_val >= 0) {
00048       /* Sign (7th) bit = 1 */
00049       mask = AMI_MASK | 0x80;
00050    } else {
00051       /* Sign bit = 0 */
00052       mask = AMI_MASK;
00053       pcm_val = -pcm_val;
00054    }
00055 
00056    /* Convert the scaled magnitude to segment number. */
00057    for (seg = 0; seg < 8; seg++) {
00058       if (pcm_val <= seg_end[seg]) {
00059          break;
00060       }
00061    }
00062    /* Combine the sign, segment, and quantization bits. */
00063    return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
00064 }
00065 #else
00066 static unsigned char linear2alaw(short sample, int full_coding)
00067 {
00068    static const unsigned exp_lut[128] = {
00069       1,1,2,2,3,3,3,3,
00070       4,4,4,4,4,4,4,4,
00071       5,5,5,5,5,5,5,5,
00072       5,5,5,5,5,5,5,5,
00073       6,6,6,6,6,6,6,6,
00074       6,6,6,6,6,6,6,6,
00075       6,6,6,6,6,6,6,6,
00076       6,6,6,6,6,6,6,6,
00077       7,7,7,7,7,7,7,7,
00078       7,7,7,7,7,7,7,7,
00079       7,7,7,7,7,7,7,7,
00080       7,7,7,7,7,7,7,7,
00081       7,7,7,7,7,7,7,7,
00082       7,7,7,7,7,7,7,7,
00083       7,7,7,7,7,7,7,7,
00084       7,7,7,7,7,7,7,7 };
00085    unsigned sign, exponent, mantissa, mag;
00086    unsigned char alawbyte;
00087    
00088    ast_alaw_get_sign_mag(sample, &sign, &mag);
00089    if (mag > 32767)
00090       mag = 32767;        /* clip the magnitude for -32768 */
00091    
00092    exponent = exp_lut[(mag >> 8) & 0x7f];
00093    mantissa = (mag >> (exponent + 3)) & 0x0f;
00094    if (mag < 0x100)
00095       exponent = 0;
00096    
00097    if (full_coding) {
00098       /* full encoding, with sign and xform */
00099       alawbyte = (unsigned char)(sign | (exponent << 4) | mantissa);
00100       alawbyte ^= AST_ALAW_AMI_MASK;
00101    } else {
00102       /* half-cooked coding -- mantissa+exponent only (for lookup tab) */
00103       alawbyte = (exponent << 4) | mantissa;
00104    }
00105    return alawbyte;
00106 }
00107 #endif
00108 
00109 #ifndef G711_NEW_ALGORITHM
00110 static inline short int alaw2linear (unsigned char alaw)
00111 {
00112    int i;
00113    int seg;
00114 
00115    alaw ^= AMI_MASK;
00116    i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
00117    seg = (((int) alaw & 0x70) >> 4);
00118    if (seg) {
00119       i = (i + 0x100) << (seg - 1);
00120    }
00121    return (short int) ((alaw & 0x80) ? i : -i);
00122 }
00123 #else
00124 static inline short alaw2linear(unsigned char alawbyte)
00125 {
00126    unsigned exponent, mantissa;
00127    short sample;
00128    
00129    alawbyte ^= AST_ALAW_AMI_MASK;
00130    exponent = (alawbyte & 0x70) >> 4;
00131    mantissa = alawbyte & 0x0f;
00132    sample = (mantissa << 4) + 8 /* rounding error */;
00133    if (exponent)
00134       sample = (sample + 0x100) << (exponent - 1);
00135    if (!(alawbyte & 0x80))
00136       sample = -sample;
00137    return sample;
00138 }
00139 #endif
00140 
00141 
00142 
00143 #ifndef G711_NEW_ALGORITHM
00144 unsigned char __ast_lin2a[8192];
00145 #else
00146 unsigned char __ast_lin2a[AST_ALAW_TAB_SIZE];
00147 #endif
00148 short __ast_alaw[256];
00149 
00150 void ast_alaw_init(void)
00151 {
00152    int i;
00153    /* 
00154     *  Set up mu-law conversion table
00155     */ 
00156 #ifndef G711_NEW_ALGORITHM
00157    for (i = 0; i < 256; i++) {
00158       __ast_alaw[i] = alaw2linear(i);
00159    }
00160    /* set up the reverse (mu-law) conversion table */
00161    for (i = -32768; i < 32768; i++) {
00162       __ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
00163    }
00164 #else
00165    for (i = 0; i < 256; i++) {
00166       __ast_alaw[i] = alaw2linear(i);
00167    }
00168    /* set up the reverse (a-law) conversion table */
00169    for (i = 0; i <= 32768; i += AST_ALAW_STEP) {
00170       AST_LIN2A_LOOKUP(i) = linear2alaw(i, 0 /* half-cooked */);
00171    }
00172 #endif
00173    
00174 #ifdef TEST_CODING_TABLES
00175    for (i = -32768; i < 32768; ++i) {
00176 #ifndef G711_NEW_ALGORITHM
00177       unsigned char e1 = linear2alaw(i);
00178 #else
00179       unsigned char e1 = linear2alaw(i, 1);
00180 #endif
00181       short d1 = alaw2linear(e1);
00182       unsigned char e2 = AST_LIN2A(i);
00183       short d2 = alaw2linear(e2);
00184       short d3 = AST_ALAW(e1);
00185       
00186       if (e1 != e2 || d1 != d3 || d2 != d3) {
00187          ast_log(LOG_WARNING, "a-Law coding tables test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d\n",
00188                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2);
00189       }
00190    }
00191    ast_log(LOG_NOTICE, "a-Law coding tables test complete.\n");
00192 #endif /* TEST_CODING_TABLES */
00193    
00194 #ifdef TEST_TANDEM_TRANSCODING
00195    /* tandem transcoding test */
00196    for (i = -32768; i < 32768; ++i) {
00197       unsigned char e1 = AST_LIN2A(i);
00198       short d1 = AST_ALAW(e1);
00199       unsigned char e2 = AST_LIN2A(d1);
00200       short d2 = AST_ALAW(e2);
00201       unsigned char e3 = AST_LIN2A(d2);
00202       short d3 = AST_ALAW(e3);
00203       
00204       if (e1 != e2 || e2 != e3 || d1 != d2 || d2 != d3) {
00205          ast_log(LOG_WARNING, "a-Law tandem transcoding test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d, d3=%d\n",
00206                i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2, (int)d3);
00207       }
00208    }
00209    ast_log(LOG_NOTICE, "a-Law tandem transcoding test complete.\n");
00210 #endif /* TEST_TANDEM_TRANSCODING */
00211    
00212 }
00213 

Generated on Wed Oct 28 11:50:51 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6