Annotation of src/usr.bin/sndiod/dsp.c, Revision 1.21
1.21 ! ratchov 1: /* $OpenBSD: dsp.c,v 1.20 2024/04/22 11:07:42 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <string.h>
18: #include "dsp.h"
19: #include "utils.h"
20:
1.17 naddy 21: const int aparams_ctltovol[128] = {
1.20 ratchov 22: 0, 65536, 68109, 70783,
23: 73562, 76450, 79451, 82570,
24: 85812, 89181, 92682, 96321,
25: 100102, 104032, 108116, 112361,
26: 116772, 121356, 126121, 131072,
27: 136218, 141566, 147123, 152899,
28: 158902, 165140, 171624, 178361,
29: 185364, 192641, 200204, 208064,
30: 216232, 224721, 233544, 242713,
31: 252241, 262144, 272436, 283131,
32: 294247, 305799, 317804, 330281,
33: 343247, 356723, 370728, 385282,
34: 400408, 416128, 432465, 449443,
35: 467088, 485425, 504482, 524288,
36: 544871, 566262, 588493, 611597,
37: 635608, 660561, 686495, 713446,
38: 741455, 770564, 800816, 832255,
39: 864929, 898885, 934175, 970850,
40: 1008965, 1048576, 1089742, 1132525,
41: 1176987, 1223194, 1271216, 1321123,
42: 1372989, 1426892, 1482910, 1541128,
43: 1601632, 1664511, 1729858, 1797771,
44: 1868350, 1941700, 2017930, 2097152,
45: 2179485, 2265049, 2353974, 2446389,
46: 2542432, 2642246, 2745978, 2853783,
47: 2965821, 3082257, 3203264, 3329021,
48: 3459716, 3595542, 3736700, 3883400,
49: 4035859, 4194304, 4358969, 4530099,
50: 4707947, 4892777, 5084864, 5284492,
51: 5491957, 5707567, 5931642, 6164513,
52: 6406527, 6658043, 6919432, 7191084,
53: 7473400, 7766800, 8071719, 8388608
1.1 ratchov 54: };
55:
1.17 naddy 56: const int resamp_filt[RESAMP_LENGTH / RESAMP_STEP + 1] = {
1.16 ratchov 57: 0, 0, 3, 9, 22, 42, 73, 116,
58: 174, 248, 341, 454, 589, 749, 934, 1148,
59: 1392, 1666, 1974, 2316, 2693, 3107, 3560, 4051,
60: 4582, 5154, 5766, 6420, 7116, 7853, 8632, 9451,
61: 10311, 11210, 12148, 13123, 14133, 15178, 16253, 17359,
62: 18491, 19647, 20824, 22018, 23226, 24443, 25665, 26888,
63: 28106, 29315, 30509, 31681, 32826, 33938, 35009, 36033,
64: 37001, 37908, 38744, 39502, 40174, 40750, 41223, 41582,
65: 41819, 41925, 41890, 41704, 41358, 40842, 40147, 39261,
66: 38176, 36881, 35366, 33623, 31641, 29411, 26923, 24169,
67: 21140, 17827, 14222, 10317, 6105, 1580, -3267, -8440,
68: -13944, -19785, -25967, -32492, -39364, -46584, -54153, -62072,
69: -70339, -78953, -87911, -97209, -106843, -116806, -127092, -137692,
70: -148596, -159795, -171276, -183025, -195029, -207271, -219735, -232401,
71: -245249, -258259, -271407, -284670, -298021, -311434, -324880, -338329,
72: -351750, -365111, -378378, -391515, -404485, -417252, -429775, -442015,
73: -453930, -465477, -476613, -487294, -497472, -507102, -516137, -524527,
74: -532225, -539181, -545344, -550664, -555090, -558571, -561055, -562490,
75: -562826, -562010, -559990, -556717, -552139, -546205, -538866, -530074,
76: -519779, -507936, -494496, -479416, -462652, -444160, -423901, -401835,
77: -377923, -352132, -324425, -294772, -263143, -229509, -193847, -156134,
78: -116348, -74474, -30494, 15601, 63822, 114174, 166661, 221283,
79: 278037, 336916, 397911, 461009, 526194, 593446, 662741, 734054,
80: 807354, 882608, 959779, 1038826, 1119706, 1202370, 1286768, 1372846,
81: 1460546, 1549808, 1640566, 1732753, 1826299, 1921130, 2017169, 2114336,
82: 2212550, 2311723, 2411770, 2512598, 2614116, 2716228, 2818836, 2921841,
83: 3025142, 3128636, 3232218, 3335782, 3439219, 3542423, 3645282, 3747687,
84: 3849526, 3950687, 4051059, 4150530, 4248987, 4346320, 4442415, 4537163,
85: 4630453, 4722177, 4812225, 4900493, 4986873, 5071263, 5153561, 5233668,
86: 5311485, 5386917, 5459872, 5530259, 5597992, 5662986, 5725160, 5784436,
87: 5840739, 5893999, 5944148, 5991122, 6034862, 6075313, 6112422, 6146142,
88: 6176430, 6203247, 6226559, 6246335, 6262551, 6275185, 6284220, 6289647,
89: 6291456, 6289647, 6284220, 6275185, 6262551, 6246335, 6226559, 6203247,
90: 6176430, 6146142, 6112422, 6075313, 6034862, 5991122, 5944148, 5893999,
91: 5840739, 5784436, 5725160, 5662986, 5597992, 5530259, 5459872, 5386917,
92: 5311485, 5233668, 5153561, 5071263, 4986873, 4900493, 4812225, 4722177,
93: 4630453, 4537163, 4442415, 4346320, 4248987, 4150530, 4051059, 3950687,
94: 3849526, 3747687, 3645282, 3542423, 3439219, 3335782, 3232218, 3128636,
95: 3025142, 2921841, 2818836, 2716228, 2614116, 2512598, 2411770, 2311723,
96: 2212550, 2114336, 2017169, 1921130, 1826299, 1732753, 1640566, 1549808,
97: 1460546, 1372846, 1286768, 1202370, 1119706, 1038826, 959779, 882608,
98: 807354, 734054, 662741, 593446, 526194, 461009, 397911, 336916,
99: 278037, 221283, 166661, 114174, 63822, 15601, -30494, -74474,
100: -116348, -156134, -193847, -229509, -263143, -294772, -324425, -352132,
101: -377923, -401835, -423901, -444160, -462652, -479416, -494496, -507936,
102: -519779, -530074, -538866, -546205, -552139, -556717, -559990, -562010,
103: -562826, -562490, -561055, -558571, -555090, -550664, -545344, -539181,
104: -532225, -524527, -516137, -507102, -497472, -487294, -476613, -465477,
105: -453930, -442015, -429775, -417252, -404485, -391515, -378378, -365111,
106: -351750, -338329, -324880, -311434, -298021, -284670, -271407, -258259,
107: -245249, -232401, -219735, -207271, -195029, -183025, -171276, -159795,
108: -148596, -137692, -127092, -116806, -106843, -97209, -87911, -78953,
109: -70339, -62072, -54153, -46584, -39364, -32492, -25967, -19785,
110: -13944, -8440, -3267, 1580, 6105, 10317, 14222, 17827,
111: 21140, 24169, 26923, 29411, 31641, 33623, 35366, 36881,
112: 38176, 39261, 40147, 40842, 41358, 41704, 41890, 41925,
113: 41819, 41582, 41223, 40750, 40174, 39502, 38744, 37908,
114: 37001, 36033, 35009, 33938, 32826, 31681, 30509, 29315,
115: 28106, 26888, 25665, 24443, 23226, 22018, 20824, 19647,
116: 18491, 17359, 16253, 15178, 14133, 13123, 12148, 11210,
117: 10311, 9451, 8632, 7853, 7116, 6420, 5766, 5154,
118: 4582, 4051, 3560, 3107, 2693, 2316, 1974, 1666,
119: 1392, 1148, 934, 749, 589, 454, 341, 248,
120: 174, 116, 73, 42, 22, 9, 3, 0,
121: 0
122: };
123:
124:
1.1 ratchov 125: /*
126: * Generate a string corresponding to the encoding in par,
127: * return the length of the resulting string.
128: */
129: int
130: aparams_enctostr(struct aparams *par, char *ostr)
131: {
132: char *p = ostr;
133:
134: *p++ = par->sig ? 's' : 'u';
135: if (par->bits > 9)
136: *p++ = '0' + par->bits / 10;
137: *p++ = '0' + par->bits % 10;
138: if (par->bps > 1) {
139: *p++ = par->le ? 'l' : 'b';
140: *p++ = 'e';
141: if (par->bps != APARAMS_BPS(par->bits) ||
142: par->bits < par->bps * 8) {
143: *p++ = par->bps + '0';
144: if (par->bits < par->bps * 8) {
145: *p++ = par->msb ? 'm' : 'l';
146: *p++ = 's';
147: *p++ = 'b';
148: }
149: }
150: }
151: *p++ = '\0';
152: return p - ostr - 1;
153: }
154:
155: /*
156: * Parse an encoding string, examples: s8, u8, s16, s16le, s24be ...
157: * set *istr to the char following the encoding. Return the number
158: * of bytes consumed.
159: */
160: int
161: aparams_strtoenc(struct aparams *par, char *istr)
162: {
163: char *p = istr;
164: int i, sig, bits, le, bps, msb;
165:
166: #define IS_SEP(c) \
167: (((c) < 'a' || (c) > 'z') && \
168: ((c) < 'A' || (c) > 'Z') && \
169: ((c) < '0' || (c) > '9'))
170:
171: /*
172: * get signedness
173: */
174: if (*p == 's') {
175: sig = 1;
176: } else if (*p == 'u') {
177: sig = 0;
178: } else
179: return 0;
180: p++;
181:
182: /*
183: * get number of bits per sample
184: */
185: bits = 0;
186: for (i = 0; i < 2; i++) {
187: if (*p < '0' || *p > '9')
188: break;
189: bits = (bits * 10) + *p - '0';
190: p++;
191: }
192: if (bits < BITS_MIN || bits > BITS_MAX)
193: return 0;
194: bps = APARAMS_BPS(bits);
195: msb = 1;
196: le = ADATA_LE;
197:
198: /*
199: * get (optional) endianness
200: */
201: if (p[0] == 'l' && p[1] == 'e') {
202: le = 1;
203: p += 2;
204: } else if (p[0] == 'b' && p[1] == 'e') {
205: le = 0;
206: p += 2;
207: } else if (IS_SEP(*p)) {
208: goto done;
209: } else
210: return 0;
211:
212: /*
213: * get (optional) number of bytes
214: */
215: if (*p >= '0' && *p <= '9') {
216: bps = *p - '0';
217: if (bps < (bits + 7) / 8 ||
218: bps > (BITS_MAX + 7) / 8)
219: return 0;
220: p++;
221:
222: /*
1.7 nicm 223: * get (optional) alignment
1.1 ratchov 224: */
225: if (p[0] == 'm' && p[1] == 's' && p[2] == 'b') {
226: msb = 1;
227: p += 3;
228: } else if (p[0] == 'l' && p[1] == 's' && p[2] == 'b') {
229: msb = 0;
230: p += 3;
231: } else if (IS_SEP(*p)) {
232: goto done;
233: } else
234: return 0;
235: } else if (!IS_SEP(*p))
236: return 0;
237:
238: done:
1.10 ratchov 239: par->msb = msb;
1.1 ratchov 240: par->sig = sig;
241: par->bits = bits;
242: par->bps = bps;
243: par->le = le;
244: return p - istr;
245: }
246:
247: /*
248: * Initialise parameters structure with the defaults natively supported
249: * by the machine.
250: */
251: void
252: aparams_init(struct aparams *par)
253: {
254: par->bps = sizeof(adata_t);
255: par->bits = ADATA_BITS;
256: par->le = ADATA_LE;
257: par->sig = 1;
258: par->msb = 0;
259: }
260:
261: /*
262: * log the given format/channels/encoding
263: */
264: void
265: aparams_log(struct aparams *par)
266: {
267: char enc[ENCMAX];
268:
269: aparams_enctostr(par, enc);
270: log_puts(enc);
271: }
272:
273: /*
274: * return true if encoding corresponds to what we store in adata_t
275: */
276: int
277: aparams_native(struct aparams *par)
278: {
1.15 ratchov 279: return par->sig &&
280: par->bps == sizeof(adata_t) &&
281: par->bits == ADATA_BITS &&
1.1 ratchov 282: (par->bps == 1 || par->le == ADATA_LE) &&
283: (par->bits == par->bps * 8 || !par->msb);
284: }
285:
286: /*
1.19 ratchov 287: * Return the number of input and output frame that would be consumed
288: * by resamp_do(p, *icnt, *ocnt).
1.1 ratchov 289: */
1.13 ratchov 290: void
1.19 ratchov 291: resamp_getcnt(struct resamp *p, int *icnt, int *ocnt)
292: {
293: long long idiff, odiff;
294: int cdiff;
295:
296: cdiff = p->oblksz - p->diff;
297: idiff = (long long)*icnt * p->oblksz;
298: odiff = (long long)*ocnt * p->iblksz;
299: if (odiff - idiff >= cdiff)
300: *ocnt = (idiff + cdiff + p->iblksz - 1) / p->iblksz;
301: else
302: *icnt = (odiff + p->diff) / p->oblksz;
303: }
304:
305: /*
306: * Resample the given number of frames. The number of output frames
307: * must match the corresponding number of input frames. Either always
308: * use icnt and ocnt such that:
309: *
310: * icnt * oblksz = ocnt * iblksz
311: *
312: * or use resamp_getcnt() to calculate the proper numbers.
313: */
314: void
315: resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt)
1.1 ratchov 316: {
317: unsigned int nch;
318: adata_t *idata;
319: unsigned int oblksz;
1.19 ratchov 320: unsigned int ifr;
1.1 ratchov 321: int s, ds, diff;
322: adata_t *odata;
323: unsigned int iblksz;
1.19 ratchov 324: unsigned int ofr;
1.1 ratchov 325: unsigned int c;
1.16 ratchov 326: int64_t f[NCHAN_MAX];
1.1 ratchov 327: adata_t *ctxbuf, *ctx;
328: unsigned int ctx_start;
1.16 ratchov 329: int q, qi, qf, n;
1.1 ratchov 330:
331: /*
332: * Partially copy structures into local variables, to avoid
333: * unnecessary indirections; this also allows the compiler to
334: * order local variables more "cache-friendly".
335: */
336: idata = in;
337: odata = out;
1.19 ratchov 338: diff = p->diff;
1.1 ratchov 339: iblksz = p->iblksz;
340: oblksz = p->oblksz;
341: ctxbuf = p->ctx;
342: ctx_start = p->ctx_start;
343: nch = p->nch;
1.19 ratchov 344: ifr = icnt;
345: ofr = ocnt;
1.1 ratchov 346:
1.19 ratchov 347: /*
348: * Start conversion.
349: */
350: #ifdef DEBUG
351: if (log_level >= 4) {
352: log_puts("resamp: copying ");
353: log_puti(ifr);
354: log_puts(" -> ");
355: log_putu(ofr);
356: log_puts(" frames, diff = ");
357: log_puti(diff);
358: log_puts("\n");
359: }
360: #endif
1.1 ratchov 361: for (;;) {
1.13 ratchov 362: if (diff >= oblksz) {
1.19 ratchov 363: if (ifr == 0)
1.1 ratchov 364: break;
1.16 ratchov 365: ctx_start = (ctx_start - 1) & (RESAMP_NCTX - 1);
1.1 ratchov 366: ctx = ctxbuf + ctx_start;
367: for (c = nch; c > 0; c--) {
368: *ctx = *idata++;
369: ctx += RESAMP_NCTX;
370: }
1.13 ratchov 371: diff -= oblksz;
1.19 ratchov 372: ifr--;
1.13 ratchov 373: } else {
1.19 ratchov 374: if (ofr == 0)
375: break;
1.16 ratchov 376:
1.18 ratchov 377: for (c = 0; c < nch; c++)
1.16 ratchov 378: f[c] = 0;
379:
380: q = diff * p->filt_step;
381: n = ctx_start;
382:
383: while (q < RESAMP_LENGTH) {
384: qi = q >> RESAMP_STEP_BITS;
385: qf = q & (RESAMP_STEP - 1);
386: s = resamp_filt[qi];
387: ds = resamp_filt[qi + 1] - s;
388: s += (int64_t)qf * ds >> RESAMP_STEP_BITS;
389: ctx = ctxbuf;
1.18 ratchov 390: for (c = 0; c < nch; c++) {
1.16 ratchov 391: f[c] += (int64_t)ctx[n] * s;
392: ctx += RESAMP_NCTX;
393: }
394: q += p->filt_cutoff;
395: n = (n + 1) & (RESAMP_NCTX - 1);
396: }
397:
1.18 ratchov 398: for (c = 0; c < nch; c++) {
1.16 ratchov 399: s = f[c] >> RESAMP_BITS;
400: s = (int64_t)s * p->filt_cutoff >> RESAMP_BITS;
401: #if ADATA_BITS == 16
402: /*
403: * In 16-bit mode, we've no room for filter
404: * overshoots, so we need to clip the signal
405: * to avoid 16-bit integers to wrap around.
406: * In 24-bit mode, samples may exceed the
407: * [-1:1] range. Later, cmap_add() will clip
408: * them, so no need to clip them here as well.
409: */
410: if (s >= ADATA_UNIT)
411: s = ADATA_UNIT - 1;
412: else if (s < -ADATA_UNIT)
413: s = -ADATA_UNIT;
414: #endif
415: *odata++ = s;
1.1 ratchov 416: }
1.19 ratchov 417:
1.13 ratchov 418: diff += iblksz;
1.19 ratchov 419: ofr--;
1.1 ratchov 420: }
421: }
1.19 ratchov 422: p->diff = diff;
423: p->ctx_start = ctx_start;
424: #ifdef DEBUG
425: if (ifr != 0) {
426: log_puts("resamp_do: ");
427: log_puti(ifr);
428: log_puts(": too many input frames\n");
429: panic();
430: }
431: if (ofr != 0) {
432: log_puts("resamp_do: ");
433: log_puti(ofr);
434: log_puts(": too many output frames\n");
435: panic();
436: }
437: #endif
438: }
439:
440: static unsigned int
441: uint_gcd(unsigned int a, unsigned int b)
442: {
443: unsigned int r;
1.13 ratchov 444:
1.19 ratchov 445: while (b > 0) {
446: r = a % b;
447: a = b;
448: b = r;
449: }
450: return a;
1.1 ratchov 451: }
452:
453: /*
454: * initialize resampler with ibufsz/obufsz factor and "nch" channels
455: */
456: void
1.9 ratchov 457: resamp_init(struct resamp *p, unsigned int iblksz,
458: unsigned int oblksz, int nch)
1.1 ratchov 459: {
1.19 ratchov 460: unsigned int g;
461:
462: /*
463: * reduce iblksz/oblksz fraction
464: */
465: g = uint_gcd(iblksz, oblksz);
466: iblksz /= g;
467: oblksz /= g;
468:
469: /*
470: * ensure weird rates don't cause integer overflow
471: */
472: while (iblksz > ADATA_UNIT || oblksz > ADATA_UNIT) {
473: iblksz >>= 1;
474: oblksz >>= 1;
475: }
476:
1.1 ratchov 477: p->iblksz = iblksz;
478: p->oblksz = oblksz;
1.19 ratchov 479: p->diff = 0;
1.1 ratchov 480: p->nch = nch;
481: p->ctx_start = 0;
1.14 miko 482: memset(p->ctx, 0, sizeof(p->ctx));
1.16 ratchov 483: if (p->iblksz < p->oblksz) {
484: p->filt_cutoff = RESAMP_UNIT;
485: p->filt_step = RESAMP_UNIT / p->oblksz;
486: } else {
487: p->filt_cutoff = (int64_t)RESAMP_UNIT * p->oblksz / p->iblksz;
488: p->filt_step = RESAMP_UNIT / p->iblksz;
489: }
1.1 ratchov 490: #ifdef DEBUG
491: if (log_level >= 3) {
492: log_puts("resamp: ");
493: log_putu(iblksz);
494: log_puts("/");
495: log_putu(oblksz);
496: log_puts("\n");
497: }
498: #endif
499: }
500:
501: /*
502: * encode "todo" frames from native to foreign encoding
503: */
504: void
505: enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
506: {
507: unsigned int f;
508: adata_t *idata;
1.8 ratchov 509: unsigned int s;
1.1 ratchov 510: unsigned int oshift;
1.8 ratchov 511: unsigned int obias;
1.1 ratchov 512: unsigned int obps;
513: unsigned int i;
514: unsigned char *odata;
515: int obnext;
516: int osnext;
517:
518: #ifdef DEBUG
519: if (log_level >= 4) {
520: log_puts("enc: copying ");
521: log_putu(todo);
522: log_puts(" frames\n");
523: }
524: #endif
525: /*
526: * Partially copy structures into local variables, to avoid
527: * unnecessary indirections; this also allows the compiler to
528: * order local variables more "cache-friendly".
529: */
530: idata = (adata_t *)in;
531: odata = out;
532: oshift = p->shift;
1.8 ratchov 533: obias = p->bias;
1.1 ratchov 534: obps = p->bps;
535: obnext = p->bnext;
536: osnext = p->snext;
537:
538: /*
539: * Start conversion.
540: */
541: odata += p->bfirst;
542: for (f = todo * p->nch; f > 0; f--) {
1.8 ratchov 543: /* convert adata to u32 */
544: s = (int)*idata++ + ADATA_UNIT;
1.1 ratchov 545: s <<= 32 - ADATA_BITS;
1.8 ratchov 546: /* convert u32 to uN */
1.1 ratchov 547: s >>= oshift;
1.8 ratchov 548: /* convert uN to sN */
549: s -= obias;
550: /* packetize sN */
1.1 ratchov 551: for (i = obps; i > 0; i--) {
552: *odata = (unsigned char)s;
553: s >>= 8;
554: odata += obnext;
555: }
556: odata += osnext;
557: }
558: }
559:
560: /*
561: * store "todo" frames of silence in foreign encoding
562: */
563: void
564: enc_sil_do(struct conv *p, unsigned char *out, int todo)
565: {
566: unsigned int f;
1.8 ratchov 567: unsigned int s;
568: unsigned int oshift;
569: int obias;
1.1 ratchov 570: unsigned int obps;
571: unsigned int i;
572: unsigned char *odata;
573: int obnext;
574: int osnext;
575:
576: #ifdef DEBUG
577: if (log_level >= 4) {
578: log_puts("enc: silence ");
579: log_putu(todo);
580: log_puts(" frames\n");
581: }
582: #endif
583: /*
584: * Partially copy structures into local variables, to avoid
585: * unnecessary indirections; this also allows the compiler to
586: * order local variables more "cache-friendly".
587: */
588: odata = out;
1.8 ratchov 589: oshift = p->shift;
590: obias = p->bias;
1.1 ratchov 591: obps = p->bps;
592: obnext = p->bnext;
593: osnext = p->snext;
594:
595: /*
596: * Start conversion.
597: */
598: odata += p->bfirst;
599: for (f = todo * p->nch; f > 0; f--) {
1.8 ratchov 600: s = ((1U << 31) >> oshift) - obias;
1.1 ratchov 601: for (i = obps; i > 0; i--) {
602: *odata = (unsigned char)s;
603: s >>= 8;
604: odata += obnext;
605: }
606: odata += osnext;
607: }
608: }
609:
610: /*
611: * initialize encoder from native to foreign encoding
612: */
613: void
614: enc_init(struct conv *p, struct aparams *par, int nch)
615: {
616: p->nch = nch;
617: p->bps = par->bps;
618: if (par->msb) {
619: p->shift = 32 - par->bps * 8;
620: } else {
621: p->shift = 32 - par->bits;
622: }
1.8 ratchov 623: if (par->sig) {
624: p->bias = (1U << 31) >> p->shift;
625: } else {
626: p->bias = 0;
1.9 ratchov 627: }
1.1 ratchov 628: if (!par->le) {
629: p->bfirst = par->bps - 1;
630: p->bnext = -1;
631: p->snext = 2 * par->bps;
632: } else {
633: p->bfirst = 0;
634: p->bnext = 1;
635: p->snext = 0;
636: }
637: #ifdef DEBUG
638: if (log_level >= 3) {
639: log_puts("enc: ");
640: aparams_log(par);
641: log_puts(", ");
642: log_puti(p->nch);
643: log_puts(" channels\n");
644: }
645: #endif
646: }
647:
648: /*
1.12 ratchov 649: * decode "todo" frames from foreign to native encoding
1.1 ratchov 650: */
651: void
652: dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
653: {
654: unsigned int f;
655: unsigned int ibps;
656: unsigned int i;
1.8 ratchov 657: unsigned int s = 0xdeadbeef;
1.1 ratchov 658: unsigned char *idata;
659: int ibnext;
660: int isnext;
1.8 ratchov 661: unsigned int ibias;
1.1 ratchov 662: unsigned int ishift;
663: adata_t *odata;
664:
665: #ifdef DEBUG
666: if (log_level >= 4) {
667: log_puts("dec: copying ");
668: log_putu(todo);
669: log_puts(" frames\n");
670: }
671: #endif
672: /*
673: * Partially copy structures into local variables, to avoid
674: * unnecessary indirections; this also allows the compiler to
675: * order local variables more "cache-friendly".
676: */
677: idata = in;
678: odata = (adata_t *)out;
679: ibps = p->bps;
680: ibnext = p->bnext;
1.8 ratchov 681: ibias = p->bias;
1.1 ratchov 682: ishift = p->shift;
683: isnext = p->snext;
684:
685: /*
686: * Start conversion.
687: */
688: idata += p->bfirst;
689: for (f = todo * p->nch; f > 0; f--) {
690: for (i = ibps; i > 0; i--) {
691: s <<= 8;
692: s |= *idata;
693: idata += ibnext;
694: }
695: idata += isnext;
1.8 ratchov 696: s += ibias;
1.1 ratchov 697: s <<= ishift;
698: s >>= 32 - ADATA_BITS;
1.8 ratchov 699: *odata++ = s - ADATA_UNIT;
1.1 ratchov 700: }
701: }
702:
703: /*
704: * initialize decoder from foreign to native encoding
705: */
706: void
707: dec_init(struct conv *p, struct aparams *par, int nch)
708: {
709: p->bps = par->bps;
710: p->nch = nch;
711: if (par->msb) {
712: p->shift = 32 - par->bps * 8;
713: } else {
714: p->shift = 32 - par->bits;
715: }
1.8 ratchov 716: if (par->sig) {
717: p->bias = (1U << 31) >> p->shift;
718: } else {
719: p->bias = 0;
1.9 ratchov 720: }
1.1 ratchov 721: if (par->le) {
722: p->bfirst = par->bps - 1;
723: p->bnext = -1;
724: p->snext = 2 * par->bps;
725: } else {
726: p->bfirst = 0;
727: p->bnext = 1;
728: p->snext = 0;
729: }
730: #ifdef DEBUG
731: if (log_level >= 3) {
732: log_puts("dec: ");
733: aparams_log(par);
734: log_puts(", ");
735: log_puti(p->nch);
736: log_puts(" channels\n");
737: }
738: #endif
739: }
740:
741: /*
742: * mix "todo" input frames on the output with the given volume
743: */
744: void
745: cmap_add(struct cmap *p, void *in, void *out, int vol, int todo)
746: {
747: adata_t *idata, *odata;
748: int i, j, nch, istart, inext, onext, ostart, y, v;
749:
750: #ifdef DEBUG
751: if (log_level >= 4) {
752: log_puts("cmap: adding ");
753: log_puti(todo);
754: log_puts(" frames\n");
755: }
756: #endif
757: idata = in;
758: odata = out;
759: ostart = p->ostart;
760: onext = p->onext;
761: istart = p->istart;
762: inext = p->inext;
763: nch = p->nch;
1.2 ratchov 764: v = vol;
1.1 ratchov 765:
766: /*
767: * map/mix input on the output
768: */
769: for (i = todo; i > 0; i--) {
770: odata += ostart;
771: idata += istart;
772: for (j = nch; j > 0; j--) {
773: y = *odata + ADATA_MUL(*idata, v);
774: if (y >= ADATA_UNIT)
775: y = ADATA_UNIT - 1;
776: else if (y < -ADATA_UNIT)
777: y = -ADATA_UNIT;
778: *odata = y;
779: idata++;
780: odata++;
781: }
782: odata += onext;
783: idata += inext;
784: }
785: }
786:
787: /*
1.12 ratchov 788: * overwrite output with "todo" input frames with the given volume
1.1 ratchov 789: */
790: void
791: cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo)
792: {
793: adata_t *idata, *odata;
794: int i, j, nch, istart, inext, onext, ostart, v;
795:
796: #ifdef DEBUG
797: if (log_level >= 4) {
798: log_puts("cmap: copying ");
799: log_puti(todo);
800: log_puts(" frames\n");
801: }
802: #endif
803: idata = in;
804: odata = out;
805: ostart = p->ostart;
806: onext = p->onext;
807: istart = p->istart;
808: inext = p->inext;
809: nch = p->nch;
810: v = vol;
811:
812: /*
813: * copy to the output buffer
814: */
815: for (i = todo; i > 0; i--) {
816: idata += istart;
1.4 ratchov 817: odata += ostart;
1.1 ratchov 818: for (j = nch; j > 0; j--) {
819: *odata = ADATA_MUL(*idata, v);
820: odata++;
821: idata++;
822: }
1.4 ratchov 823: odata += onext;
1.1 ratchov 824: idata += inext;
825: }
826: }
827:
828: /*
829: * initialize channel mapper, to map a subset of input channel range
830: * into a subset of the output channel range
831: */
832: void
833: cmap_init(struct cmap *p,
834: int imin, int imax, int isubmin, int isubmax,
835: int omin, int omax, int osubmin, int osubmax)
836: {
1.21 ! ratchov 837: int inch, onch, nch;
1.1 ratchov 838:
1.21 ! ratchov 839: /*
! 840: * Ignore channels outside of the available sets
! 841: */
! 842: if (isubmin < imin)
! 843: isubmin = imin;
! 844: if (isubmax > imax)
! 845: isubmax = imax;
! 846: if (osubmin < omin)
! 847: osubmin = omin;
! 848: if (osubmax > omax)
! 849: osubmax = omax;
! 850:
! 851: /*
! 852: * Shrink the input or the output subset to make both subsets of
! 853: * the same size
! 854: */
! 855: inch = isubmax - isubmin + 1;
! 856: onch = osubmax - osubmin + 1;
! 857: nch = (inch < onch) ? inch : onch;
! 858: isubmax = isubmin + nch - 1;
! 859: osubmax = osubmin + nch - 1;
! 860:
! 861: p->ostart = osubmin - omin;
! 862: p->onext = omax - osubmax;
! 863: p->istart = isubmin - imin;
! 864: p->inext = imax - isubmax;
! 865: p->nch = nch;
1.1 ratchov 866: #ifdef DEBUG
867: if (log_level >= 3) {
868: log_puts("cmap: nch = ");
869: log_puti(p->nch);
870: log_puts(", ostart = ");
871: log_puti(p->ostart);
872: log_puts(", onext = ");
873: log_puti(p->onext);
874: log_puts(", istart = ");
875: log_puti(p->istart);
1.6 ratchov 876: log_puts(", inext = ");
1.1 ratchov 877: log_puti(p->inext);
878: log_puts("\n");
879: }
880: #endif
881: }