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