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