1 /**
2  * Copyright 1993 Network Computing Devices, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name Network Computing Devices, Inc. not be
9  * used in advertising or publicity pertaining to distribution of this
10  * software without specific, written prior permission.
11  *
12  * THIS SOFTWARE IS PROVIDED 'AS-IS'.  NETWORK COMPUTING DEVICES, INC.,
13  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
14  * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15  * PARTICULAR PURPOSE, OR NONINFRINGEMENT.  IN NO EVENT SHALL NETWORK
16  * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
17  * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
18  * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
19  * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * $NCDId: @(#)convutil.c,v 1.2 1994/04/07 20:42:26 greg Exp $
23  */
24 
25 
26 /* data format conversion routines */
27 
28 #include "Alibint.h"
29 #include <audio/fileutil.h>
30 
31 #undef convert
32 #define convert(_type, _convert)					      \
33 do									      \
34 {									      \
35     _type x;								      \
36 									      \
37     x = *(_type *) s;							      \
38     *d-- = _convert;							      \
39     s -= sizeof(x);							      \
40 } while (--samples)
41 
42 #define ulawToLinear(_x) ulawToLinearTable[_x]
43 
44 static unsigned short ulawToLinearTable[] =
45 {
46     0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
47     0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
48     0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
49     0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
50     0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
51     0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
52     0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
53     0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
54     0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
55     0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
56     0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
57     0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
58     0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
59     0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
60     0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
61     0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
62     0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
63     0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
64     0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
65     0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
66     0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
67     0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
68     0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
69     0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
70     0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
71     0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
72     0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
73     0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
74     0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
75     0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
76     0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
77     0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
78 };
79 
80 int
AuConvertDataToShort(int dataFormat,int numBytes,AuPointer data)81 AuConvertDataToShort(int dataFormat, int numBytes, AuPointer data)
82 {
83     char           *s;
84     short          *d;
85     int             samples;
86 
87     samples = numBytes / AuSizeofFormat(dataFormat);
88 
89     if (!samples)
90 	return 0;
91 
92     s = ((char *) data) + numBytes - AuSizeofFormat(dataFormat);
93     d = (short *) (((char *) data) + samples * sizeof(short)) - 1;
94 
95     switch (dataFormat)
96     {
97 	case AuFormatULAW8:
98 	    convert(unsigned char, ulawToLinear(x));
99 	    break;
100 	case AuFormatLinearUnsigned8:
101 	    convert(unsigned char, (x - 128) << 8);
102 	    break;
103 	case AuFormatLinearSigned8:
104 	    convert(char, x << 8);
105 	    break;
106 	case AuFormatLinearSigned16MSB:
107 	    if (NAS_LITTLE_ENDIAN)
108 		convert(short, ((((unsigned short) x) >> 8) | (x << 8)));
109 #if 0
110 	    else
111 		convert(short, x);
112 #endif
113 	    break;
114 	case AuFormatLinearUnsigned16MSB:
115 	    if (NAS_LITTLE_ENDIAN)
116 		convert(short,
117 			(((((unsigned short) x) >> 8) | (x << 8)) ^ 0x8000));
118 	    else
119 		convert(short, x ^ 0x8000);
120 	    break;
121 	case AuFormatLinearSigned16LSB:
122 	    if (NAS_BIG_ENDIAN)
123 		convert(short, ((((unsigned short) x) >> 8) | (x << 8)));
124 #if 0
125 	    else
126 		convert(short, x);
127 #endif
128 	    break;
129 	case AuFormatLinearUnsigned16LSB:
130 	    if (NAS_BIG_ENDIAN)
131 		convert(short,
132 			(((((unsigned short) x) >> 8) | (x << 8)) ^ 0x8000));
133 	    else
134 		convert(short, x ^ 0x8000);
135 	    break;
136 	default:
137 	    return -1;
138     }
139 
140     return 0;
141 }
142 
143 #undef convert
144 #define convert(_type, _convert)					      \
145 {									      \
146     _type *_d = (_type *) d;						      \
147     short x;								      \
148 									      \
149     do									      \
150     {									      \
151 	x = *s++;							      \
152 	*_d++ = _convert;						      \
153     } while (--samples);						      \
154 }
155 
156 /**
157  * This routine converts from linear to ulaw.
158  *
159  * Craig Reese: IDA/Supercomputing Research Center
160  * Joe Campbell: Department of Defense
161  * 29 September 1989
162  *
163  * References:
164  * 1) CCITT Recommendation G.711  (very difficult to follow)
165  * 2) "A New Digital Technique for Implementation of Any
166  *     Continuous PCM Companding Law," Villeret, Michel,
167  *     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
168  *     1973, pg. 11.12-11.17
169  * 3) MIL-STD-188-113,"Interoperability and Performance Standards
170  *     for Analog-to_Digital Conversion Techniques,"
171  *     17 February 1987
172  *
173  * Input: Signed 16 bit linear sample
174  * Output: 8 bit ulaw sample
175  */
176 
177 #if 0
178 #define ZEROTRAP				/* turn on the trap as per
179 						 * the MIL-STD */
180 #define CLIP 32635
181 #endif
182 
183 #define BIAS 0x84				/* define the add-in bias for
184 						 * 16 bit samples */
185 
186 static unsigned char
linearToUlaw(short sample)187 linearToUlaw(short sample)
188 {
189     static int      exp_lut[256] =
190     {
191 	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
192 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
193 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
194 	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
195 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
196 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
197 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
198 	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
199 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
200 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
201 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
202 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
203 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
204 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
205 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
206 	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
207     };
208     short           sign,
209                     exponent,
210                     mantissa;
211     unsigned char   ulawbyte;
212 
213     /* Get the sample into sign-magnitude. */
214     sign = (sample >> 8) & 0x80;/* set aside the sign */
215 
216     if (sign)
217 	sample = -sample;	/* get magnitude */
218 #ifdef CLIP
219     if (sample > CLIP)
220 	sample = CLIP;		/* clip the magnitude */
221 #endif
222     /* Convert from 16 bit linear to ulaw. */
223     sample = sample + BIAS;
224     exponent = exp_lut[(sample >> 7) & 0xff];
225     mantissa = (sample >> (exponent + 3)) & 0xf;
226     ulawbyte = ~(sign | (exponent << 4) | mantissa);
227 #ifdef ZEROTRAP
228     if (!ulawbyte)
229 	ulawbyte = 0x02;	/* optional CCITT trap */
230 #endif
231 
232     return ulawbyte;
233 }
234 
235 int
AuConvertShortToData(int dataFormat,int numBytes,AuPointer data)236 AuConvertShortToData(
237                      int             dataFormat,
238                      int             numBytes,
239                      AuPointer          data
240                      )
241 {
242     char           *d;
243     short          *s;
244     int             samples;
245 
246     samples = numBytes / sizeof(short);
247 
248     if (!samples)
249 	return 0;
250 
251     s = (short *) data;
252     d = (char *) data;
253 
254     switch (dataFormat)
255     {
256 	case AuFormatULAW8:
257 	    convert(unsigned char, linearToUlaw(x));
258 	    break;
259 	case AuFormatLinearUnsigned8:
260 	    convert(unsigned char, (x >> 8) + 128);
261 	    break;
262 	case AuFormatLinearSigned8:
263 	    convert(char, x >> 8);
264 	    break;
265 	case AuFormatLinearSigned16MSB:
266 	    if (NAS_LITTLE_ENDIAN)
267 		convert(short, ((((unsigned short) x) >> 8) | (x << 8)));
268 #if 0
269 	    else
270 	    {
271 		convert(short, x);
272 	    }
273 #endif
274 	    break;
275 	case AuFormatLinearUnsigned16MSB:
276 	    if (NAS_LITTLE_ENDIAN)
277 	    {
278 		convert(short,
279 			(((((unsigned short) x) >> 8) | (x << 8)) ^ 0x8000));
280 	    }
281 	    else
282 	    {
283 		convert(short, x ^ 0x8000);
284 	    }
285 	    break;
286 	case AuFormatLinearSigned16LSB:
287 	    if (NAS_BIG_ENDIAN)
288 		convert(short, ((((unsigned short) x) >> 8) | (x << 8)));
289 #if 0
290 	    else
291 	    {
292 		convert(short, x);
293 	    }
294 #endif
295 	    break;
296 	case AuFormatLinearUnsigned16LSB:
297 	    if (NAS_BIG_ENDIAN)
298 	    {
299 		convert(short,
300 			(((((unsigned short) x) >> 8) | (x << 8)) ^ 0x8000));
301 	    }
302 	    else
303 	    {
304 		convert(short, x ^ 0x8000);
305 	    }
306 	    break;
307 	default:
308 	    return -1;
309     }
310 
311     return 0;
312 }
313