2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief a-Law to Signed linear conversion
23 * \author Mark Spencer <markster@digium.com>
28 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
30 #include "asterisk/alaw.h"
32 #ifndef G711_NEW_ALGORITHM
35 static inline unsigned char linear2alaw(short int linear
)
40 static int seg_end
[8] =
42 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
47 /* Sign (7th) bit = 1 */
48 mask
= AMI_MASK
| 0x80;
55 /* Convert the scaled magnitude to segment number. */
56 for (seg
= 0; seg
< 8; seg
++) {
57 if (pcm_val
<= seg_end
[seg
]) {
61 /* Combine the sign, segment, and quantization bits. */
62 return ((seg
<< 4) | ((pcm_val
>> ((seg
) ? (seg
+ 3) : 4)) & 0x0F)) ^ mask
;
65 static unsigned char linear2alaw(short sample
, int full_coding
)
67 static const unsigned exp_lut
[128] = {
84 unsigned sign
, exponent
, mantissa
, mag
;
85 unsigned char alawbyte
;
87 ast_alaw_get_sign_mag(sample
, &sign
, &mag
);
89 mag
= 32767; /* clip the magnitude for -32768 */
91 exponent
= exp_lut
[(mag
>> 8) & 0x7f];
92 mantissa
= (mag
>> (exponent
+ 3)) & 0x0f;
97 /* full encoding, with sign and xform */
98 alawbyte
= (unsigned char)(sign
| (exponent
<< 4) | mantissa
);
99 alawbyte
^= AST_ALAW_AMI_MASK
;
101 /* half-cooked coding -- mantissa+exponent only (for lookup tab) */
102 alawbyte
= (exponent
<< 4) | mantissa
;
108 #ifndef G711_NEW_ALGORITHM
109 static inline short int alaw2linear (unsigned char alaw
)
115 i
= ((alaw
& 0x0F) << 4) + 8 /* rounding error */;
116 seg
= (((int) alaw
& 0x70) >> 4);
118 i
= (i
+ 0x100) << (seg
- 1);
120 return (short int) ((alaw
& 0x80) ? i
: -i
);
123 static inline short alaw2linear(unsigned char alawbyte
)
125 unsigned exponent
, mantissa
;
128 alawbyte
^= AST_ALAW_AMI_MASK
;
129 exponent
= (alawbyte
& 0x70) >> 4;
130 mantissa
= alawbyte
& 0x0f;
131 sample
= (mantissa
<< 4) + 8 /* rounding error */;
133 sample
= (sample
+ 0x100) << (exponent
- 1);
134 if (!(alawbyte
& 0x80))
142 #ifndef G711_NEW_ALGORITHM
143 unsigned char __ast_lin2a
[8192];
145 unsigned char __ast_lin2a
[AST_ALAW_TAB_SIZE
];
147 short __ast_alaw
[256];
149 void ast_alaw_init(void)
153 * Set up mu-law conversion table
155 #ifndef G711_NEW_ALGORITHM
156 for (i
= 0; i
< 256; i
++) {
157 __ast_alaw
[i
] = alaw2linear(i
);
159 /* set up the reverse (mu-law) conversion table */
160 for (i
= -32768; i
< 32768; i
++) {
161 __ast_lin2a
[((unsigned short)i
) >> 3] = linear2alaw(i
);
164 for (i
= 0; i
< 256; i
++) {
165 __ast_alaw
[i
] = alaw2linear(i
);
167 /* set up the reverse (a-law) conversion table */
168 for (i
= 0; i
<= 32768; i
+= AST_ALAW_STEP
) {
169 AST_LIN2A_LOOKUP(i
) = linear2alaw(i
, 0 /* half-cooked */);
173 #ifdef TEST_CODING_TABLES
174 for (i
= -32768; i
< 32768; ++i
) {
175 #ifndef G711_NEW_ALGORITHM
176 unsigned char e1
= linear2alaw(i
);
178 unsigned char e1
= linear2alaw(i
, 1);
180 short d1
= alaw2linear(e1
);
181 unsigned char e2
= AST_LIN2A(i
);
182 short d2
= alaw2linear(e2
);
183 short d3
= AST_ALAW(e1
);
185 if (e1
!= e2
|| d1
!= d3
|| d2
!= d3
) {
186 ast_log(LOG_WARNING
, "a-Law coding tables test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d\n",
187 i
, (unsigned)e1
, (unsigned)e2
, (int)d1
, (int)d2
);
190 ast_log(LOG_NOTICE
, "a-Law coding tables test complete.\n");
191 #endif /* TEST_CODING_TABLES */
193 #ifdef TEST_TANDEM_TRANSCODING
194 /* tandem transcoding test */
195 for (i
= -32768; i
< 32768; ++i
) {
196 unsigned char e1
= AST_LIN2A(i
);
197 short d1
= AST_ALAW(e1
);
198 unsigned char e2
= AST_LIN2A(d1
);
199 short d2
= AST_ALAW(e2
);
200 unsigned char e3
= AST_LIN2A(d2
);
201 short d3
= AST_ALAW(e3
);
203 if (e1
!= e2
|| e2
!= e3
|| d1
!= d2
|| d2
!= d3
) {
204 ast_log(LOG_WARNING
, "a-Law tandem transcoding test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d, d3=%d\n",
205 i
, (unsigned)e1
, (unsigned)e2
, (int)d1
, (int)d2
, (int)d3
);
208 ast_log(LOG_NOTICE
, "a-Law tandem transcoding test complete.\n");
209 #endif /* TEST_TANDEM_TRANSCODING */