Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


alaw.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18 
19 /*! \file
20  *
21  * \brief a-Law to Signed linear conversion
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
33 
34 #include "asterisk/alaw.h"
35 #include "asterisk/logger.h"
36 
37 #ifndef G711_NEW_ALGORITHM
38 #define AMI_MASK 0x55
39 
40 static inline unsigned char linear2alaw(short int linear)
41 {
42  int mask;
43  int seg;
44  int pcm_val;
45  static int seg_end[8] =
46  {
47  0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
48  };
49 
50  pcm_val = linear;
51  if (pcm_val >= 0) {
52  /* Sign (7th) bit = 1 */
53  mask = AMI_MASK | 0x80;
54  } else {
55  /* Sign bit = 0 */
56  mask = AMI_MASK;
57  pcm_val = -pcm_val;
58  }
59 
60  /* Convert the scaled magnitude to segment number. */
61  for (seg = 0; seg < 8; seg++) {
62  if (pcm_val <= seg_end[seg]) {
63  break;
64  }
65  }
66  /* Combine the sign, segment, and quantization bits. */
67  return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
68 }
69 #else
70 static unsigned char linear2alaw(short sample, int full_coding)
71 {
72  static const unsigned exp_lut[128] = {
73  1,1,2,2,3,3,3,3,
74  4,4,4,4,4,4,4,4,
75  5,5,5,5,5,5,5,5,
76  5,5,5,5,5,5,5,5,
77  6,6,6,6,6,6,6,6,
78  6,6,6,6,6,6,6,6,
79  6,6,6,6,6,6,6,6,
80  6,6,6,6,6,6,6,6,
81  7,7,7,7,7,7,7,7,
82  7,7,7,7,7,7,7,7,
83  7,7,7,7,7,7,7,7,
84  7,7,7,7,7,7,7,7,
85  7,7,7,7,7,7,7,7,
86  7,7,7,7,7,7,7,7,
87  7,7,7,7,7,7,7,7,
88  7,7,7,7,7,7,7,7 };
89  unsigned sign, exponent, mantissa, mag;
90  unsigned char alawbyte;
91 
92  ast_alaw_get_sign_mag(sample, &sign, &mag);
93  if (mag > 32767)
94  mag = 32767; /* clip the magnitude for -32768 */
95 
96  exponent = exp_lut[(mag >> 8) & 0x7f];
97  mantissa = (mag >> (exponent + 3)) & 0x0f;
98  if (mag < 0x100)
99  exponent = 0;
100 
101  if (full_coding) {
102  /* full encoding, with sign and xform */
103  alawbyte = (unsigned char)(sign | (exponent << 4) | mantissa);
104  alawbyte ^= AST_ALAW_AMI_MASK;
105  } else {
106  /* half-cooked coding -- mantissa+exponent only (for lookup tab) */
107  alawbyte = (exponent << 4) | mantissa;
108  }
109  return alawbyte;
110 }
111 #endif
112 
113 #ifndef G711_NEW_ALGORITHM
114 static inline short int alaw2linear (unsigned char alaw)
115 {
116  int i;
117  int seg;
118 
119  alaw ^= AMI_MASK;
120  i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
121  seg = (((int) alaw & 0x70) >> 4);
122  if (seg) {
123  i = (i + 0x100) << (seg - 1);
124  }
125  return (short int) ((alaw & 0x80) ? i : -i);
126 }
127 #else
128 static inline short alaw2linear(unsigned char alawbyte)
129 {
130  unsigned exponent, mantissa;
131  short sample;
132 
133  alawbyte ^= AST_ALAW_AMI_MASK;
134  exponent = (alawbyte & 0x70) >> 4;
135  mantissa = alawbyte & 0x0f;
136  sample = (mantissa << 4) + 8 /* rounding error */;
137  if (exponent)
138  sample = (sample + 0x100) << (exponent - 1);
139  if (!(alawbyte & 0x80))
140  sample = -sample;
141  return sample;
142 }
143 #endif
144 
145 
146 
147 #ifndef G711_NEW_ALGORITHM
148 unsigned char __ast_lin2a[8192];
149 #else
150 unsigned char __ast_lin2a[AST_ALAW_TAB_SIZE];
151 #endif
152 short __ast_alaw[256];
153 
154 void ast_alaw_init(void)
155 {
156  int i;
157  /*
158  * Set up mu-law conversion table
159  */
160 #ifndef G711_NEW_ALGORITHM
161  for (i = 0; i < 256; i++) {
162  __ast_alaw[i] = alaw2linear(i);
163  }
164  /* set up the reverse (mu-law) conversion table */
165  for (i = -32768; i < 32768; i++) {
166  __ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
167  }
168 #else
169  for (i = 0; i < 256; i++) {
170  __ast_alaw[i] = alaw2linear(i);
171  }
172  /* set up the reverse (a-law) conversion table */
173  for (i = 0; i <= 32768; i += AST_ALAW_STEP) {
174  AST_LIN2A_LOOKUP(i) = linear2alaw(i, 0 /* half-cooked */);
175  }
176 #endif
177 
178 #ifdef TEST_CODING_TABLES
179  for (i = -32768; i < 32768; ++i) {
180 #ifndef G711_NEW_ALGORITHM
181  unsigned char e1 = linear2alaw(i);
182 #else
183  unsigned char e1 = linear2alaw(i, 1);
184 #endif
185  short d1 = alaw2linear(e1);
186  unsigned char e2 = AST_LIN2A(i);
187  short d2 = alaw2linear(e2);
188  short d3 = AST_ALAW(e1);
189 
190  if (e1 != e2 || d1 != d3 || d2 != d3) {
191  ast_log(LOG_WARNING, "a-Law coding tables test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d\n",
192  i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2);
193  }
194  }
195  ast_log(LOG_NOTICE, "a-Law coding tables test complete.\n");
196 #endif /* TEST_CODING_TABLES */
197 
198 #ifdef TEST_TANDEM_TRANSCODING
199  /* tandem transcoding test */
200  for (i = -32768; i < 32768; ++i) {
201  unsigned char e1 = AST_LIN2A(i);
202  short d1 = AST_ALAW(e1);
203  unsigned char e2 = AST_LIN2A(d1);
204  short d2 = AST_ALAW(e2);
205  unsigned char e3 = AST_LIN2A(d2);
206  short d3 = AST_ALAW(e3);
207 
208  if (e1 != e2 || e2 != e3 || d1 != d2 || d2 != d3) {
209  ast_log(LOG_WARNING, "a-Law tandem transcoding test failed on %d: e1=%u, e2=%u, d1=%d, d2=%d, d3=%d\n",
210  i, (unsigned)e1, (unsigned)e2, (int)d1, (int)d2, (int)d3);
211  }
212  }
213  ast_log(LOG_NOTICE, "a-Law tandem transcoding test complete.\n");
214 #endif /* TEST_TANDEM_TRANSCODING */
215 
216 }
217 
Asterisk main include file. File version handling, generic pbx functions.
#define LOG_WARNING
Definition: logger.h:144
#define AST_ALAW(a)
Definition: alaw.h:84
short __ast_alaw[256]
Definition: alaw.c:152
unsigned char __ast_lin2a[8192]
converts signed linear to alaw
Definition: alaw.c:148
#define AST_ALAW_AMI_MASK
Definition: alaw.h:36
void ast_alaw_init(void)
To init the alaw to slinear conversion stuff, this needs to be run.
Definition: alaw.c:154
#define AST_ALAW_STEP
Definition: alaw.h:33
static short int alaw2linear(unsigned char alaw)
Definition: alaw.c:114
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define AST_ALAW_TAB_SIZE
Definition: alaw.h:34
Support for logging to various files, console and syslog Configuration in file logger.conf.
static unsigned char linear2alaw(short int linear)
Definition: alaw.c:40
#define AMI_MASK
Definition: alaw.c:38
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define AST_LIN2A(a)
Definition: alaw.h:50