blob: 0927253d3b4097d29d9291791b86288bb65acbf7 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include "g711_pcm_convert.h"
2
3
4#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
5#define QUANT_MASK (0xf) /* Quantization field mask. */
6#define NSEGS (8) /* Number of A-law segments. */
7#define SEG_SHIFT (4) /* Left shift for segment number. */
8#define SEG_MASK (0x70) /* Segment field mask. */
9#define BIAS (0x84) /* Bias for linear code. */
10
11
12static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
13 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
14 };
15
16/* copy from CCITT G.711 specifications */
17unsigned char _u2a[128] = { /* u- to A-law conversions */
18 1, 1, 2, 2, 3, 3, 4, 4,
19 5, 5, 6, 6, 7, 7, 8, 8,
20 9, 10, 11, 12, 13, 14, 15, 16,
21 17, 18, 19, 20, 21, 22, 23, 24,
22 25, 27, 29, 31, 33, 34, 35, 36,
23 37, 38, 39, 40, 41, 42, 43, 44,
24 46, 48, 49, 50, 51, 52, 53, 54,
25 55, 56, 57, 58, 59, 60, 61, 62,
26 64, 65, 66, 67, 68, 69, 70, 71,
27 72, 73, 74, 75, 76, 77, 78, 79,
28 81, 82, 83, 84, 85, 86, 87, 88,
29 89, 90, 91, 92, 93, 94, 95, 96,
30 97, 98, 99, 100, 101, 102, 103, 104,
31 105, 106, 107, 108, 109, 110, 111, 112,
32 113, 114, 115, 116, 117, 118, 119, 120,
33 121, 122, 123, 124, 125, 126, 127, 128
34};
35
36unsigned char _a2u[128] = { /* A- to u-law conversions */
37 1, 3, 5, 7, 9, 11, 13, 15,
38 16, 17, 18, 19, 20, 21, 22, 23,
39 24, 25, 26, 27, 28, 29, 30, 31,
40 32, 32, 33, 33, 34, 34, 35, 35,
41 36, 37, 38, 39, 40, 41, 42, 43,
42 44, 45, 46, 47, 48, 48, 49, 49,
43 50, 51, 52, 53, 54, 55, 56, 57,
44 58, 59, 60, 61, 62, 63, 64, 64,
45 65, 66, 67, 68, 69, 70, 71, 72,
46 73, 74, 75, 76, 77, 78, 79, 79,
47 80, 81, 82, 83, 84, 85, 86, 87,
48 88, 89, 90, 91, 92, 93, 94, 95,
49 96, 97, 98, 99, 100, 101, 102, 103,
50 104, 105, 106, 107, 108, 109, 110, 111,
51 112, 113, 114, 115, 116, 117, 118, 119,
52 120, 121, 122, 123, 124, 125, 126, 127
53};
54
55
56static short search(short val, short* table, short size)
57{
58 short i;
59 for (i = 0; i < size; i++) {
60 if (val <= *table++) {
61 return (i);
62 }
63 }
64 return (size);
65}
66
67/**
68 * @brief Convert a 16-bit linear PCM value to 8-bit A-law
69 *
70 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
71 *
72 * Linear Input Code Compressed Code
73 * ------------------------ ---------------
74 * 0000000wxyza 000wxyz
75 * 0000001wxyza 001wxyz
76 * 000001wxyzab 010wxyz
77 * 00001wxyzabc 011wxyz
78 * 0001wxyzabcd 100wxyz
79 * 001wxyzabcde 101wxyz
80 * 01wxyzabcdef 110wxyz
81 * 1wxyzabcdefg 111wxyz
82 *
83 * For further information see John C. Bellamy's Digital Telephony, 1982,
84 * John Wiley & Sons, pps 98-111 and 472-476.
85 */
86unsigned char linear2alaw(short pcm_val) /* 2's complement (16-bit range) */
87{
88 short mask;
89 short seg;
90 unsigned char aval;
91
92 if (pcm_val >= 0) {
93 mask = 0xD5; /* sign (7th) bit = 1 */
94 } else {
95 mask = 0x55; /* sign bit = 0 */
96 pcm_val = -pcm_val - 8;
97 }
98
99 /* Convert the scaled magnitude to segment number. */
100 seg = search(pcm_val, seg_end, 8);
101
102 /* Combine the sign, segment, and quantization bits. */
103
104 if (seg >= 8) { /* out of range, return maximum value. */
105 return (0x7F ^ mask);
106 } else {
107 aval = seg << SEG_SHIFT;
108 if (seg < 2) {
109 aval |= (pcm_val >> 4) & QUANT_MASK;
110 } else {
111 aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
112 }
113 return (aval ^ mask);
114 }
115}
116
117/**
118 * @brief Convert an A-law value to 16-bit linear PCM
119 *
120 */
121short alaw2linear(unsigned char a_val)
122{
123 short t;
124 short seg;
125
126 a_val ^= 0x55;
127 t = (a_val & QUANT_MASK) << 4;
128 seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
129
130 switch (seg) {
131 case 0:
132 t += 8;
133 break;
134 case 1:
135 t += 0x108;
136 break;
137 default:
138 t += 0x108;
139 t <<= seg - 1;
140 }
141
142 return ((a_val & SIGN_BIT) ? t : -t);
143}
144
145/**
146 * @brief Convert a linear PCM value to u-law
147 *
148 * In order to simplify the encoding process, the original linear magnitude
149 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
150 * (33 - 8191). The result can be seen in the following encoding table:
151 *
152 * Biased Linear Input Code Compressed Code
153 * ------------------------ ---------------
154 * 00000001wxyza 000wxyz
155 * 0000001wxyzab 001wxyz
156 * 000001wxyzabc 010wxyz
157 * 00001wxyzabcd 011wxyz
158 * 0001wxyzabcde 100wxyz
159 * 001wxyzabcdef 101wxyz
160 * 01wxyzabcdefg 110wxyz
161 * 1wxyzabcdefgh 111wxyz
162 *
163 * Each biased linear code has a leading 1 which identifies the segment
164 * number. The value of the segment number is equal to 7 minus the number
165 * of leading 0's. The quantization interval is directly available as the
166 * four bits wxyz. * The trailing bits (a - h) are ignored.
167 *
168 * Ordinarily the complement of the resulting code word is used for
169 * transmission, and so the code word is complemented before it is returned.
170 *
171 * For further information see John C. Bellamy's Digital Telephony, 1982,
172 * John Wiley & Sons, pps 98-111 and 472-476.
173 */
174unsigned char linear2ulaw(int pcm_val) /* 2's complement (16-bit range) */
175{
176 short mask;
177 short seg;
178 unsigned char uval;
179
180 /* Get the sign and the magnitude of the value. */
181 if (pcm_val < 0) {
182 pcm_val = BIAS - pcm_val;
183 mask = 0x7F;
184 } else {
185 pcm_val += BIAS;
186 mask = 0xFF;
187 }
188
189 /* Convert the scaled magnitude to segment number. */
190 seg = search(pcm_val, seg_end, 8);
191
192 /*
193 * Combine the sign, segment, quantization bits;
194 * and complement the code word.
195 */
196 if (seg >= 8) { /* out of range, return maximum value. */
197 return (0x7F ^ mask);
198 } else {
199 uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
200 return (uval ^ mask);
201 }
202}
203
204/**
205 * @brief Convert a u-law value to 16-bit linear PCM
206 *
207 * First, a biased linear code is derived from the code word. An unbiased
208 * output can then be obtained by subtracting 33 from the biased code.
209 *
210 * Note that this function expects to be passed the complement of the
211 * original code word. This is in keeping with ISDN conventions.
212 */
213int ulaw2linear(unsigned char u_val)
214{
215 short t;
216
217 /* Complement to obtain normal u-law value. */
218 u_val = ~u_val;
219
220 /*
221 * Extract and bias the quantization bits. Then
222 * shift up by the segment number and subtract out the bias.
223 */
224 t = ((u_val & QUANT_MASK) << 3) + BIAS;
225 t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
226
227 return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
228}
229
230/**
231 * @brief A-law to u-law conversion
232 *
233 * @param aval A-law value
234 * @return unsigned char u-law value
235 */
236unsigned char alaw2ulaw(unsigned char aval)
237{
238 aval &= 0xff;
239 return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
240 (0x7F ^ _a2u[aval ^ 0x55]));
241}
242
243/**
244 * @brief u-law to A-law conversion
245 *
246 * @param uval u-law value
247 * @return unsigned char A-law value
248 */
249unsigned char ulaw2alaw(unsigned char uval)
250{
251 uval &= 0xff;
252 return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
253 (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
254}
255
256/**
257 * @brief pcm data encode to g711 data
258 *
259 * user should be responsible for pCodecbit memmory
260 *
261 * @param pCodecBits store g711 encoded data
262 * @param pBuffer pcm raw data
263 * @param BufferSize pcm data len
264 * @param type g711 data type
265 * @return int encode data length
266 */
267int G711EnCode(char* pCodecBits, char* pBuffer, int BufferSize, enum g711type type)
268{
269 int i;
270 unsigned char* codecbits = (unsigned char*)pCodecBits;
271 short* buffer = (short*)pBuffer;
272
273 if (pCodecBits == 0 || pBuffer == 0 || BufferSize <= 0) {
274 return -1;
275 }
276
277 if (type == G711ALAW) {
278 for (i = 0; i < BufferSize / 2; i++) {
279 codecbits[i] = linear2alaw(buffer[i]);
280 }
281 } else {
282 for (i = 0; i < BufferSize / 2; i++) {
283 codecbits[i] = linear2ulaw(buffer[i]);
284 }
285 }
286
287 return BufferSize / 2;
288}
289
290/**
291 * @brief g711 data decode to pcm data
292 *
293 * user should be responsible for pRawData memmory
294 *
295 * @param pRawData store uncoded pcm data
296 * @param pBuffer g711 encoded data
297 * @param BufferSize g711 data len
298 * @param type g711 data type
299 * @return int pcm data len
300 */
301int G711Decode(char* pRawData, char* pBuffer, int BufferSize, enum g711type type)
302{
303 int i;
304 short* out_data = (short*)pRawData;
305 unsigned char* buffer = (unsigned char*)pBuffer;
306
307 if (pRawData == 0 || pBuffer == 0 || BufferSize <= 0) {
308 return -1;
309 }
310
311 if (type == G711ALAW) {
312 for (i = 0; i < BufferSize; i++) {
313 out_data[i] = alaw2linear(buffer[i]);
314 }
315 } else {
316 for (i = 0; i < BufferSize; i++) {
317 out_data[i] = ulaw2linear(buffer[i]);
318 }
319 }
320
321 return BufferSize * 2;
322}
323
324/**
325 * @brief g711 u-law data and a-law data convert
326 *
327 * @param alawdata g711 a-law data
328 * @param ulawdata g711 u-lwa data
329 * @param datasize input data length
330 * @param type target g711 data type
331 * @return int sucess:1; failed:0
332 */
333int G711TypeChange(unsigned char* alawdata, unsigned char* ulawdata, int datasize, enum g711type type)
334{
335 int i;
336
337 if (alawdata == 0 || ulawdata == 0 || datasize <= 0) {
338 return 0;
339 }
340
341 if (type == G711ALAW) {
342 for (i = 0; i < datasize; i++) {
343 alawdata[i] = ulaw2alaw(ulawdata[i]);
344 }
345 } else {
346 for (i = 0; i < datasize; i++) {
347 ulawdata[i] = alaw2ulaw(alawdata[i]);
348 }
349 }
350 return 1;
351}