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

Generated on Fri Jun 19 12:09:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7