Code: Select all
1 /*
2 * mktab.c --
3 *
4 * Tables for mulaw
5 *
32 */
33
34 #ifndef lint
35 static char rcsid[] =
36 "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/audio/mktab.c,v 1.6 2002/02/03 03:11:42 lim Exp $";
37 #endif
38
39 #include <stdio.h>
40 #include <math.h>
41 #include <sys/types.h>
42 #include "mulaw.h"
43
44 #define BIAS 0x84
45 #define CLIP 32635
46
47 u_char
48 st_linear_to_ulaw(register int linear)
49 {
50 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
51 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
52 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
53 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
54 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
55 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
56 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
57 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
58 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
59 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
60 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
61 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
62 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
63 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
64 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
65 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
66 register int sign, exponent, mantissa;
67 register u_char ulawbyte;
68
69 /* Get the value into sign-magnitude. */
70 sign = (linear >> 8) & 0x80;
71 if (sign != 0) {
72 /* sign extend the value, just in case */
73 linear |= 0xffff0000;
74 linear = -linear;
75 }
76 if (linear > CLIP)
77 linear = CLIP;
78
79 /* Convert from 16 bit linear to ulaw. */
80 linear += BIAS;
81 exponent = exp_lut[(linear >> 7) & 0xFF];
82 mantissa = (linear >> (exponent + 3)) & 0x0F;
83 ulawbyte = ~(sign | (exponent << 4) | mantissa);
84 return ulawbyte;
85 }
86
87 int
88 st_ulaw_to_linear(ulawbyte)
89 u_char ulawbyte;
90 {
91 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
92 int sign, exponent, mantissa, sample;
93
94 ulawbyte = ~ulawbyte;
95 sign = (ulawbyte & 0x80);
96 exponent = (ulawbyte >> 4) & 0x07;
97 mantissa = ulawbyte & 0x0F;
98 sample = exp_lut[exponent] + (mantissa << (exponent + 3)) +
99 (1 << (exponent + 2));
100 if (sign != 0)
101 sample = -sample;
102 /*
103 * ulaw maps zero to full-scale negative. This is a very poor
104 * choice given that most i/o failure modes stick zero in the
105 * buffer. So, to save our ears, we map ulaw zero to linear zero.
106 */
107 return (ulawbyte == 0xff? 0 : sample);
108 }
109
110 tab_tolin(f)
111 register FILE *f;
112 {
113 register int i, j;
114
115 fprintf(f, "const short mulawtolin[256] = {\n");
116 for (i = 0; i < 256; ) {
117 putc('\t', f);
118 for (j = i + 8; i < j; ++i)
119 fprintf(f, "%d, ", st_ulaw_to_linear(i));
120 putc('\n', f);
121 }
122 fprintf(f, "};\n");
123 }
124
125 tab_tomu(f)
126 register FILE *f;
127 {
128 register int i, j;
129
130 fprintf(f, "const unsigned char lintomulaw[65536] = {\n");
131 for (i = 0; i < 65536; ) {
132 putc('\t', f);
133 for (j = i + 8; i < j; ++i)
134 fprintf(f, "%d, ", st_linear_to_ulaw(i));
135 putc('\n', f);
136 }
137 fprintf(f, "};\n");
138 }
139
140 /*
141 * build a linear to mulaw lookup table extended by 1
142 * bit to handle clipping in the table lookup rather
143 * than testing each sample.
144 */
145 tab_tomuX(f)
146 register FILE *f;
147 {
148 register int i, j;
149
150 fprintf(f, "const unsigned char lintomulawX[65536*2] = {\n");
151 /* positive half */
152 for (i = 0; i < 32768; ) {
153 putc('\t', f);
154 for (j = i + 8; i < j; ++i)
155 fprintf(f, "%d, ", st_linear_to_ulaw(i));
156 putc('\n', f);
157 }
158 /* positive overflow (clipped) */
159 for (i = 32768; i < 65536; ) {
160 putc('\t', f);
161 for (j = i + 8; i < j; ++i)
162 fprintf(f, "%d, ", 0x80);
163 putc('\n', f);
164 }
165 /* negative overflow (clipped) */
166 for (i = 65536; i < 98304; ) {
167 putc('\t', f);
168 for (j = i + 8; i < j; ++i)
169 fprintf(f, "%d, ", 0x01);
170 putc('\n', f);
171 }
172 /* negative half */
173 for (i = 98304; i < 131072; ) {
174 putc('\t', f);
175 for (j = i + 8; i < j; ++i)
176 fprintf(f, "%d, ", st_linear_to_ulaw(i));
177 putc('\n', f);
178 }
179 fprintf(f, "};\n");
180 }
181
182 void
183 prtone(f, u)
184 register FILE *f;
185 register int u;
186 {
187 if (u < -CLIP)
188 u = -CLIP;
189 else if (u > CLIP)
190 u = CLIP;
191 fprintf(f, "%d, ", st_linear_to_ulaw(u));
192 }
193
194 tab_sum(f)
195 register FILE *f;
196 {
197 register int i, j, k, u;
198
199 fprintf(f, "const unsigned char mulawsum[256*256] = {\n");
200 for (i = 0; i < 256; ++i) {
201 fprintf(f, "/* %d */\n", i);
202 u = st_ulaw_to_linear(i);
203 for (j = 0; j < 256; ) {
204 putc('\t', f);
205 for (k = j + 8; j < k; ++j)
206 prtone(f, u + st_ulaw_to_linear(j));
207 putc('\n', f);
208 }
209 }
210 fprintf(f, "};\n");
211 }
212
213 void
214 prt8(f, u, us)
215 register FILE *f;
216 register int u;
217 register int* us;
218 {
219 register int k;
220
221 putc('\t', f);
222 for (k = 0; k < 8; ++k)
223 prtone(f, u + us[k]);
224 putc('\n', f);
225 }
226
227 int
228 prtup64(f, u, uj)
229 register FILE *f;
230 register int u, uj;
231 {
232 register int k;
233 int us[64], uabs, uk;
234
235 /*
236 * compute the 64 values that would precede uj in a mulaw
237 * table (assuming a gain of 17/16 which is roughly right
238 * for large uj). Do them in reverse order since mulaw
239 * values are complemented.
240 */
241 uabs = (uj>=0? uj : -uj) << 4;
242 for (k = 64; --k >= 0; ) {
243 uk = uabs >> 4;
244 us[k] = uj>=0? uk : -uk;
245 uabs += uk;
246 }
247 for (k = 0; k < 64; k += 8)
248 prt8(f, u, us + k);
249 }
250
251 int
252 prtlow64(f, u, uj)
253 register FILE *f;
254 register int u, uj;
255 {
256 register int k;
257 int us[64], uabs, uk;
258
259 /*
260 * compute the 64 values that would follow uj in a mulaw
261 * table.
262 */
263 uabs = 1 << 4;
264 for (k = 48; --k >= 0; ) {
265 uk = uabs >> 4;
266 us[k] = uj>=0? uk : -uk;
267 uabs += uk;
268 }
269 for (k = 64; --k >= 48; ) {
270 us[k] = 0;
271 }
272 for (k = 0; k < 64; k += 8)
273 prt8(f, u, us + k);
274 }
275
276 tab_mugain(f)
277 register FILE *f;
278 {
279 register int i, j, k;
280 #define M 16.
281 double g = 1.;
282 double gi = pow(M, (double)1. / 32.);
283
284 fprintf(f, "const unsigned char mugaintab[64*256] = {\n");
285 for (i = 0; i < 64; ++i) {
286 fprintf(f, "/* step %d (gain %g) */\n", i - 32, g / M);
287
288 for (j = 0; j < 256; ) {
289 putc('\t', f);
290 for (k = j + 8; j < k; ++j) {
291 double v = g / M * (double)st_ulaw_to_linear(j);
292 prtone(f, (int)v);
293 }
294 putc('\n', f);
295 }
296 g *= gi;
297 }
298 fprintf(f, "};\n");
299 #undef M
300 }
301
302 /*
303 * Output a table that maps mulaw samples to power levels, where
304 * the power level is given by p = log_2(x^2) (i.e., not really db).
305 * p is expressed in 32-bit fixed point, with 19 bits of fraction.
306 * Since ulaw samples range over 16 bits (linear), we need 32 bits
307 * to represent log_2(x^2). To compute the power in a frame, we add
308 * 160 of these samples, so we need to be able to represent 32 * 160 = 0x1400,
309 * with the encoding. Thus, we need 13 bits for the integer part,
310 * which gives 19 bits of fraction. This encoding will allow the
311 * frame size to go to 256. Note that all the values are positive
312 * since the smallest linear value is 4 (except for 0, which we will
313 * just encode as 0).
314 */
315 #ifdef notdef
316 tab_mudb(f)
317 register FILE *f;
318 {
319 register int i, j;
320 double log2 = log((double)2);
321
322 fprintf(f, "const unsigned long mulawtodb[256] = {\n");
323 for (i = 0; i < 256; ) {
324 putc('\t', f);
325 for (j = i + 4; i < j; ++i) {
326 u_long s;
327 double d = (double)st_ulaw_to_linear(i);
328 if (d != 0) {
329 d = d * d;
330 d = log(d) / log2;
331 d *= (double)(1 << MUDB_FRACBITS);
332 }
333 fprintf(f, "0x%lx, ", (u_long)irint(d));
334 }
335 putc('\n', f);
336 }
337 fprintf(f, "};\n");
338 }
339
340 tab_x(f)
341 register FILE *f;
342 {
343 register int i;
344
345 for (i = 0; i <= CLIP; ++i) {
346 int u = st_linear_to_ulaw(i);
347 printf("%d\n", ~u & 0x7f);
348 }
349 }
350
351 tab_xx(f)
352 register FILE *f;
353 {
354 register int i;
355
356 for (i = 0; i <= CLIP; ++i) {
357 int u = st_linear_to_ulaw(i);
358 printf("%d\n", st_ulaw_to_linear(u));
359 }
360 }
361 #endif
362
363 main(int argc, char* argv[])
364 {
365 if (argc != 2)
366 exit(1);
367 if (strcmp(argv[1], "-mulaw") == 0) {
368 tab_tolin(stdout);
369 tab_tomu(stdout);
370 } else if (strcmp(argv[1], "-sum") == 0)
371 tab_sum(stdout);
372 else if (strcmp(argv[1], "-scale") == 0)
373 tab_mugain(stdout);
374 else if (strcmp(argv[1], "-muX") == 0)
375 tab_tomuX(stdout);
376 #ifdef notdef
377 else if (strcmp(argv[1], "-db") == 0)
378 tab_mudb(stdout);
379 else if (strcmp(argv[1], "-x") == 0)
380 tab_x(stdout);
381 else if (strcmp(argv[1], "-xx") == 0)
382 tab_xx(stdout);
383 #endif
384 else
385 exit(1);
386 exit(0);
387 }
388