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

Generated on Thu Apr 16 06:27:06 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6