1/*
2 * This source code is a product of Sun Microsystems, Inc. and is provided
3 * for unrestricted use.  Users may copy or modify this source code without
4 * charge.
5 *
6 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
7 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
8 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
9 *
10 * Sun source code is provided with no support and without any obligation on
11 * the part of Sun Microsystems, Inc. to assist in its use, correction,
12 * modification or enhancement.
13 *
14 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
15 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
16 * OR ANY PART THEREOF.
17 *
18 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
19 * or profits or other special, indirect and consequential damages, even if
20 * Sun has been advised of the possibility of such damages.
21 *
22 * Sun Microsystems, Inc.
23 * 2550 Garcia Avenue
24 * Mountain View, California  94043
25 */
26
27/*
28 * g711.c
29 *
30 * u-law, A-law and linear PCM conversions.
31 */
32
33#include "snack.h"
34
35/*
36 * Functions Snack_Lin2Alaw, Snack_Lin2Mulaw have been updated to correctly
37 * convert unquantized 16 bit values.
38 * Tables for direct u- to A-law and A- to u-law conversions have been
39 * corrected.
40 * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
41 * bli@cpk.auc.dk
42 *
43 */
44
45#define	SIGN_BIT	(0x80)		/* Sign bit for a A-law byte. */
46#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
47#define	NSEGS		(8)		/* Number of A-law segments. */
48#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
49#define	SEG_MASK	(0x70)		/* Segment field mask. */
50
51static short seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
52			    0x1FF, 0x3FF, 0x7FF, 0xFFF};
53static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
54			    0x3FF, 0x7FF, 0xFFF, 0x1FFF};
55
56/* copy from CCITT G.711 specifications */
57unsigned char _u2a[128] = {			/* u- to A-law conversions */
58	1,	1,	2,	2,	3,	3,	4,	4,
59	5,	5,	6,	6,	7,	7,	8,	8,
60	9,	10,	11,	12,	13,	14,	15,	16,
61	17,	18,	19,	20,	21,	22,	23,	24,
62	25,	27,	29,	31,	33,	34,	35,	36,
63	37,	38,	39,	40,	41,	42,	43,	44,
64	46,	48,	49,	50,	51,	52,	53,	54,
65	55,	56,	57,	58,	59,	60,	61,	62,
66	64,	65,	66,	67,	68,	69,	70,	71,
67	72,	73,	74,	75,	76,	77,	78,	79,
68/* corrected:
69	81,	82,	83,	84,	85,	86,	87,	88,
70   should be: */
71	80,	82,	83,	84,	85,	86,	87,	88,
72	89,	90,	91,	92,	93,	94,	95,	96,
73	97,	98,	99,	100,	101,	102,	103,	104,
74	105,	106,	107,	108,	109,	110,	111,	112,
75	113,	114,	115,	116,	117,	118,	119,	120,
76	121,	122,	123,	124,	125,	126,	127,	128};
77
78unsigned char _a2u[128] = {			/* A- to u-law conversions */
79	1,	3,	5,	7,	9,	11,	13,	15,
80	16,	17,	18,	19,	20,	21,	22,	23,
81	24,	25,	26,	27,	28,	29,	30,	31,
82	32,	32,	33,	33,	34,	34,	35,	35,
83	36,	37,	38,	39,	40,	41,	42,	43,
84	44,	45,	46,	47,	48,	48,	49,	49,
85	50,	51,	52,	53,	54,	55,	56,	57,
86	58,	59,	60,	61,	62,	63,	64,	64,
87	65,	66,	67,	68,	69,	70,	71,	72,
88/* corrected:
89	73,	74,	75,	76,	77,	78,	79,	79,
90   should be: */
91	73,	74,	75,	76,	77,	78,	79,	80,
92
93	80,	81,	82,	83,	84,	85,	86,	87,
94	88,	89,	90,	91,	92,	93,	94,	95,
95	96,	97,	98,	99,	100,	101,	102,	103,
96	104,	105,	106,	107,	108,	109,	110,	111,
97	112,	113,	114,	115,	116,	117,	118,	119,
98	120,	121,	122,	123,	124,	125,	126,	127};
99
100static short
101search(
102	short		val,
103	short		*table,
104	short		size)
105{
106	short		i;
107
108	for (i = 0; i < size; i++) {
109		if (val <= *table++)
110			return (i);
111	}
112	return (size);
113}
114
115/*
116 * Snack_Lin2Alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
117 *
118 * Snack_Lin2Alaw() accepts an 16-bit integer and encodes it as A-law data.
119 *
120 *		Linear Input Code	Compressed Code
121 *	------------------------	---------------
122 *	0000000wxyza			000wxyz
123 *	0000001wxyza			001wxyz
124 *	000001wxyzab			010wxyz
125 *	00001wxyzabc			011wxyz
126 *	0001wxyzabcd			100wxyz
127 *	001wxyzabcde			101wxyz
128 *	01wxyzabcdef			110wxyz
129 *	1wxyzabcdefg			111wxyz
130 *
131 * For further information see John C. Bellamy's Digital Telephony, 1982,
132 * John Wiley & Sons, pps 98-111 and 472-476.
133 */
134
135unsigned char
136Snack_Lin2Alaw(
137	short		pcm_val)	/* 2's complement (16-bit range) */
138{
139	short		mask;
140	short		seg;
141	unsigned char	aval;
142
143	pcm_val = pcm_val >> 3;
144
145	if (pcm_val >= 0) {
146		mask = 0xD5;		/* sign (7th) bit = 1 */
147	} else {
148		mask = 0x55;		/* sign bit = 0 */
149		pcm_val = -pcm_val - 1;
150	}
151
152	/* Convert the scaled magnitude to segment number. */
153	seg = search(pcm_val, seg_aend, 8);
154
155	/* Combine the sign, segment, and quantization bits. */
156
157	if (seg >= 8)		/* out of range, return maximum value. */
158		return (unsigned char) (0x7F ^ mask);
159	else {
160		aval = (unsigned char) seg << SEG_SHIFT;
161		if (seg < 2)
162			aval |= (pcm_val >> 1) & QUANT_MASK;
163		else
164			aval |= (pcm_val >> seg) & QUANT_MASK;
165		return (aval ^ mask);
166	}
167}
168
169/*
170 * Snack_Alaw2Lin() - Convert an A-law value to 16-bit linear PCM
171 *
172 */
173short
174Snack_Alaw2Lin(
175	unsigned char	a_val)
176{
177	short		t;
178	short		seg;
179
180	a_val ^= 0x55;
181
182	t = (a_val & QUANT_MASK) << 4;
183	seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
184	switch (seg) {
185	case 0:
186		t += 8;
187		break;
188	case 1:
189		t += 0x108;
190		break;
191	default:
192		t += 0x108;
193		t <<= seg - 1;
194	}
195	return ((a_val & SIGN_BIT) ? t : -t);
196}
197
198#define	BIAS		(0x84)		/* Bias for linear code. */
199#define CLIP            8159
200
201/*
202 * Snack_Lin2Mulaw() - Convert a linear PCM value to u-law
203 *
204 * In order to simplify the encoding process, the original linear magnitude
205 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
206 * (33 - 8191). The result can be seen in the following encoding table:
207 *
208 *	Biased Linear Input Code	Compressed Code
209 *	------------------------	---------------
210 *	00000001wxyza			000wxyz
211 *	0000001wxyzab			001wxyz
212 *	000001wxyzabc			010wxyz
213 *	00001wxyzabcd			011wxyz
214 *	0001wxyzabcde			100wxyz
215 *	001wxyzabcdef			101wxyz
216 *	01wxyzabcdefg			110wxyz
217 *	1wxyzabcdefgh			111wxyz
218 *
219 * Each biased linear code has a leading 1 which identifies the segment
220 * number. The value of the segment number is equal to 7 minus the number
221 * of leading 0's. The quantization interval is directly available as the
222 * four bits wxyz.  * The trailing bits (a - h) are ignored.
223 *
224 * Ordinarily the complement of the resulting code word is used for
225 * transmission, and so the code word is complemented before it is returned.
226 *
227 * For further information see John C. Bellamy's Digital Telephony, 1982,
228 * John Wiley & Sons, pps 98-111 and 472-476.
229 */
230unsigned char
231Snack_Lin2Mulaw(
232	short		pcm_val)	/* 2's complement (16-bit range) */
233{
234	short		mask;
235	short		seg;
236	unsigned char	uval;
237
238	/* Get the sign and the magnitude of the value. */
239	pcm_val = pcm_val >> 2;
240	if (pcm_val < 0) {
241		pcm_val = -pcm_val;
242		mask = 0x7F;
243	} else {
244		mask = 0xFF;
245	}
246        if ( pcm_val > CLIP ) pcm_val = CLIP;		/* clip the magnitude */
247	pcm_val += (BIAS >> 2);
248
249	/* Convert the scaled magnitude to segment number. */
250	seg = search(pcm_val, seg_uend, 8);
251
252	/*
253	 * Combine the sign, segment, quantization bits;
254	 * and complement the code word.
255	 */
256	if (seg >= 8)		/* out of range, return maximum value. */
257		return (unsigned char) (0x7F ^ mask);
258	else {
259		uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
260		return (uval ^ mask);
261	}
262
263}
264
265/*
266 * Snack_Mulaw2Lin() - Convert a u-law value to 16-bit linear PCM
267 *
268 * First, a biased linear code is derived from the code word. An unbiased
269 * output can then be obtained by subtracting 33 from the biased code.
270 *
271 * Note that this function expects to be passed the complement of the
272 * original code word. This is in keeping with ISDN conventions.
273 */
274short
275Snack_Mulaw2Lin(
276	unsigned char	u_val)
277{
278	short		t;
279
280	/* Complement to obtain normal u-law value. */
281	u_val = ~u_val;
282
283	/*
284	 * Extract and bias the quantization bits. Then
285	 * shift up by the segment number and subtract out the bias.
286	 */
287	t = ((u_val & QUANT_MASK) << 3) + BIAS;
288	t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
289
290	return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
291}
292
293/* A-law to u-law conversion */
294unsigned char
295alaw2ulaw(
296	unsigned char	aval)
297{
298	aval &= 0xff;
299	return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
300	    (0x7F ^ _a2u[aval ^ 0x55]));
301}
302
303/* u-law to A-law conversion */
304unsigned char
305ulaw2alaw(
306	unsigned char	uval)
307{
308	uval &= 0xff;
309	return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
310	    (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
311}
312
313