Annotation of src/usr.bin/sndiod/dsp.c, Revision 1.17
1.17 ! naddy 1: /* $OpenBSD: dsp.c,v 1.16 2021/01/11 14:26:00 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: /*
272: * resample the given number of frames
273: */
1.13 ratchov 274: void
1.1 ratchov 275: resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo)
276: {
277: unsigned int nch;
278: adata_t *idata;
279: unsigned int oblksz;
280: int s, ds, diff;
281: adata_t *odata;
282: unsigned int iblksz;
283: unsigned int c;
1.16 ratchov 284: int64_t f[NCHAN_MAX];
1.1 ratchov 285: adata_t *ctxbuf, *ctx;
286: unsigned int ctx_start;
1.16 ratchov 287: int q, qi, qf, n;
1.1 ratchov 288:
1.13 ratchov 289: #ifdef DEBUG
290: if (todo % p->iblksz != 0) {
291: log_puts("resamp_do: partial blocks not supported\n");
292: panic();
293: }
294: #endif
295:
1.1 ratchov 296: /*
297: * Partially copy structures into local variables, to avoid
298: * unnecessary indirections; this also allows the compiler to
299: * order local variables more "cache-friendly".
300: */
301: idata = in;
302: odata = out;
1.13 ratchov 303: diff = p->oblksz;
1.1 ratchov 304: iblksz = p->iblksz;
305: oblksz = p->oblksz;
306: ctxbuf = p->ctx;
307: ctx_start = p->ctx_start;
308: nch = p->nch;
309:
310: for (;;) {
1.13 ratchov 311: if (diff >= oblksz) {
312: if (todo == 0)
1.1 ratchov 313: break;
1.16 ratchov 314: ctx_start = (ctx_start - 1) & (RESAMP_NCTX - 1);
1.1 ratchov 315: ctx = ctxbuf + ctx_start;
316: for (c = nch; c > 0; c--) {
317: *ctx = *idata++;
318: ctx += RESAMP_NCTX;
319: }
1.13 ratchov 320: diff -= oblksz;
321: todo--;
322: } else {
1.16 ratchov 323:
324: for (c = nch; c > 0; c--)
325: f[c] = 0;
326:
327: q = diff * p->filt_step;
328: n = ctx_start;
329:
330: while (q < RESAMP_LENGTH) {
331: qi = q >> RESAMP_STEP_BITS;
332: qf = q & (RESAMP_STEP - 1);
333: s = resamp_filt[qi];
334: ds = resamp_filt[qi + 1] - s;
335: s += (int64_t)qf * ds >> RESAMP_STEP_BITS;
336: ctx = ctxbuf;
337: for (c = nch; c > 0; c--) {
338: f[c] += (int64_t)ctx[n] * s;
339: ctx += RESAMP_NCTX;
340: }
341: q += p->filt_cutoff;
342: n = (n + 1) & (RESAMP_NCTX - 1);
343: }
344:
1.1 ratchov 345: for (c = nch; c > 0; c--) {
1.16 ratchov 346: s = f[c] >> RESAMP_BITS;
347: s = (int64_t)s * p->filt_cutoff >> RESAMP_BITS;
348: #if ADATA_BITS == 16
349: /*
350: * In 16-bit mode, we've no room for filter
351: * overshoots, so we need to clip the signal
352: * to avoid 16-bit integers to wrap around.
353: * In 24-bit mode, samples may exceed the
354: * [-1:1] range. Later, cmap_add() will clip
355: * them, so no need to clip them here as well.
356: */
357: if (s >= ADATA_UNIT)
358: s = ADATA_UNIT - 1;
359: else if (s < -ADATA_UNIT)
360: s = -ADATA_UNIT;
361: #endif
362: *odata++ = s;
1.1 ratchov 363: }
1.13 ratchov 364: diff += iblksz;
1.1 ratchov 365: }
366: }
1.13 ratchov 367:
1.1 ratchov 368: p->ctx_start = ctx_start;
369: }
370:
371: /*
372: * initialize resampler with ibufsz/obufsz factor and "nch" channels
373: */
374: void
1.9 ratchov 375: resamp_init(struct resamp *p, unsigned int iblksz,
376: unsigned int oblksz, int nch)
1.1 ratchov 377: {
378: p->iblksz = iblksz;
379: p->oblksz = oblksz;
380: p->nch = nch;
381: p->ctx_start = 0;
1.14 miko 382: memset(p->ctx, 0, sizeof(p->ctx));
1.16 ratchov 383: if (p->iblksz < p->oblksz) {
384: p->filt_cutoff = RESAMP_UNIT;
385: p->filt_step = RESAMP_UNIT / p->oblksz;
386: } else {
387: p->filt_cutoff = (int64_t)RESAMP_UNIT * p->oblksz / p->iblksz;
388: p->filt_step = RESAMP_UNIT / p->iblksz;
389: }
1.1 ratchov 390: #ifdef DEBUG
391: if (log_level >= 3) {
392: log_puts("resamp: ");
393: log_putu(iblksz);
394: log_puts("/");
395: log_putu(oblksz);
396: log_puts("\n");
397: }
398: #endif
399: }
400:
401: /*
402: * encode "todo" frames from native to foreign encoding
403: */
404: void
405: enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
406: {
407: unsigned int f;
408: adata_t *idata;
1.8 ratchov 409: unsigned int s;
1.1 ratchov 410: unsigned int oshift;
1.8 ratchov 411: unsigned int obias;
1.1 ratchov 412: unsigned int obps;
413: unsigned int i;
414: unsigned char *odata;
415: int obnext;
416: int osnext;
417:
418: #ifdef DEBUG
419: if (log_level >= 4) {
420: log_puts("enc: copying ");
421: log_putu(todo);
422: log_puts(" frames\n");
423: }
424: #endif
425: /*
426: * Partially copy structures into local variables, to avoid
427: * unnecessary indirections; this also allows the compiler to
428: * order local variables more "cache-friendly".
429: */
430: idata = (adata_t *)in;
431: odata = out;
432: oshift = p->shift;
1.8 ratchov 433: obias = p->bias;
1.1 ratchov 434: obps = p->bps;
435: obnext = p->bnext;
436: osnext = p->snext;
437:
438: /*
439: * Start conversion.
440: */
441: odata += p->bfirst;
442: for (f = todo * p->nch; f > 0; f--) {
1.8 ratchov 443: /* convert adata to u32 */
444: s = (int)*idata++ + ADATA_UNIT;
1.1 ratchov 445: s <<= 32 - ADATA_BITS;
1.8 ratchov 446: /* convert u32 to uN */
1.1 ratchov 447: s >>= oshift;
1.8 ratchov 448: /* convert uN to sN */
449: s -= obias;
450: /* packetize sN */
1.1 ratchov 451: for (i = obps; i > 0; i--) {
452: *odata = (unsigned char)s;
453: s >>= 8;
454: odata += obnext;
455: }
456: odata += osnext;
457: }
458: }
459:
460: /*
461: * store "todo" frames of silence in foreign encoding
462: */
463: void
464: enc_sil_do(struct conv *p, unsigned char *out, int todo)
465: {
466: unsigned int f;
1.8 ratchov 467: unsigned int s;
468: unsigned int oshift;
469: int obias;
1.1 ratchov 470: unsigned int obps;
471: unsigned int i;
472: unsigned char *odata;
473: int obnext;
474: int osnext;
475:
476: #ifdef DEBUG
477: if (log_level >= 4) {
478: log_puts("enc: silence ");
479: log_putu(todo);
480: log_puts(" frames\n");
481: }
482: #endif
483: /*
484: * Partially copy structures into local variables, to avoid
485: * unnecessary indirections; this also allows the compiler to
486: * order local variables more "cache-friendly".
487: */
488: odata = out;
1.8 ratchov 489: oshift = p->shift;
490: obias = p->bias;
1.1 ratchov 491: obps = p->bps;
492: obnext = p->bnext;
493: osnext = p->snext;
494:
495: /*
496: * Start conversion.
497: */
498: odata += p->bfirst;
499: for (f = todo * p->nch; f > 0; f--) {
1.8 ratchov 500: s = ((1U << 31) >> oshift) - obias;
1.1 ratchov 501: for (i = obps; i > 0; i--) {
502: *odata = (unsigned char)s;
503: s >>= 8;
504: odata += obnext;
505: }
506: odata += osnext;
507: }
508: }
509:
510: /*
511: * initialize encoder from native to foreign encoding
512: */
513: void
514: enc_init(struct conv *p, struct aparams *par, int nch)
515: {
516: p->nch = nch;
517: p->bps = par->bps;
518: if (par->msb) {
519: p->shift = 32 - par->bps * 8;
520: } else {
521: p->shift = 32 - par->bits;
522: }
1.8 ratchov 523: if (par->sig) {
524: p->bias = (1U << 31) >> p->shift;
525: } else {
526: p->bias = 0;
1.9 ratchov 527: }
1.1 ratchov 528: if (!par->le) {
529: p->bfirst = par->bps - 1;
530: p->bnext = -1;
531: p->snext = 2 * par->bps;
532: } else {
533: p->bfirst = 0;
534: p->bnext = 1;
535: p->snext = 0;
536: }
537: #ifdef DEBUG
538: if (log_level >= 3) {
539: log_puts("enc: ");
540: aparams_log(par);
541: log_puts(", ");
542: log_puti(p->nch);
543: log_puts(" channels\n");
544: }
545: #endif
546: }
547:
548: /*
1.12 ratchov 549: * decode "todo" frames from foreign to native encoding
1.1 ratchov 550: */
551: void
552: dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo)
553: {
554: unsigned int f;
555: unsigned int ibps;
556: unsigned int i;
1.8 ratchov 557: unsigned int s = 0xdeadbeef;
1.1 ratchov 558: unsigned char *idata;
559: int ibnext;
560: int isnext;
1.8 ratchov 561: unsigned int ibias;
1.1 ratchov 562: unsigned int ishift;
563: adata_t *odata;
564:
565: #ifdef DEBUG
566: if (log_level >= 4) {
567: log_puts("dec: copying ");
568: log_putu(todo);
569: log_puts(" frames\n");
570: }
571: #endif
572: /*
573: * Partially copy structures into local variables, to avoid
574: * unnecessary indirections; this also allows the compiler to
575: * order local variables more "cache-friendly".
576: */
577: idata = in;
578: odata = (adata_t *)out;
579: ibps = p->bps;
580: ibnext = p->bnext;
1.8 ratchov 581: ibias = p->bias;
1.1 ratchov 582: ishift = p->shift;
583: isnext = p->snext;
584:
585: /*
586: * Start conversion.
587: */
588: idata += p->bfirst;
589: for (f = todo * p->nch; f > 0; f--) {
590: for (i = ibps; i > 0; i--) {
591: s <<= 8;
592: s |= *idata;
593: idata += ibnext;
594: }
595: idata += isnext;
1.8 ratchov 596: s += ibias;
1.1 ratchov 597: s <<= ishift;
598: s >>= 32 - ADATA_BITS;
1.8 ratchov 599: *odata++ = s - ADATA_UNIT;
1.1 ratchov 600: }
601: }
602:
603: /*
604: * initialize decoder from foreign to native encoding
605: */
606: void
607: dec_init(struct conv *p, struct aparams *par, int nch)
608: {
609: p->bps = par->bps;
610: p->nch = nch;
611: if (par->msb) {
612: p->shift = 32 - par->bps * 8;
613: } else {
614: p->shift = 32 - par->bits;
615: }
1.8 ratchov 616: if (par->sig) {
617: p->bias = (1U << 31) >> p->shift;
618: } else {
619: p->bias = 0;
1.9 ratchov 620: }
1.1 ratchov 621: if (par->le) {
622: p->bfirst = par->bps - 1;
623: p->bnext = -1;
624: p->snext = 2 * par->bps;
625: } else {
626: p->bfirst = 0;
627: p->bnext = 1;
628: p->snext = 0;
629: }
630: #ifdef DEBUG
631: if (log_level >= 3) {
632: log_puts("dec: ");
633: aparams_log(par);
634: log_puts(", ");
635: log_puti(p->nch);
636: log_puts(" channels\n");
637: }
638: #endif
639: }
640:
641: /*
642: * mix "todo" input frames on the output with the given volume
643: */
644: void
645: cmap_add(struct cmap *p, void *in, void *out, int vol, int todo)
646: {
647: adata_t *idata, *odata;
648: int i, j, nch, istart, inext, onext, ostart, y, v;
649:
650: #ifdef DEBUG
651: if (log_level >= 4) {
652: log_puts("cmap: adding ");
653: log_puti(todo);
654: log_puts(" frames\n");
655: }
656: #endif
657: idata = in;
658: odata = out;
659: ostart = p->ostart;
660: onext = p->onext;
661: istart = p->istart;
662: inext = p->inext;
663: nch = p->nch;
1.2 ratchov 664: v = vol;
1.1 ratchov 665:
666: /*
667: * map/mix input on the output
668: */
669: for (i = todo; i > 0; i--) {
670: odata += ostart;
671: idata += istart;
672: for (j = nch; j > 0; j--) {
673: y = *odata + ADATA_MUL(*idata, v);
674: if (y >= ADATA_UNIT)
675: y = ADATA_UNIT - 1;
676: else if (y < -ADATA_UNIT)
677: y = -ADATA_UNIT;
678: *odata = y;
679: idata++;
680: odata++;
681: }
682: odata += onext;
683: idata += inext;
684: }
685: }
686:
687: /*
1.12 ratchov 688: * overwrite output with "todo" input frames with the given volume
1.1 ratchov 689: */
690: void
691: cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo)
692: {
693: adata_t *idata, *odata;
694: int i, j, nch, istart, inext, onext, ostart, v;
695:
696: #ifdef DEBUG
697: if (log_level >= 4) {
698: log_puts("cmap: copying ");
699: log_puti(todo);
700: log_puts(" frames\n");
701: }
702: #endif
703: idata = in;
704: odata = out;
705: ostart = p->ostart;
706: onext = p->onext;
707: istart = p->istart;
708: inext = p->inext;
709: nch = p->nch;
710: v = vol;
711:
712: /*
713: * copy to the output buffer
714: */
715: for (i = todo; i > 0; i--) {
716: idata += istart;
1.4 ratchov 717: odata += ostart;
1.1 ratchov 718: for (j = nch; j > 0; j--) {
719: *odata = ADATA_MUL(*idata, v);
720: odata++;
721: idata++;
722: }
1.4 ratchov 723: odata += onext;
1.1 ratchov 724: idata += inext;
725: }
726: }
727:
728: /*
729: * initialize channel mapper, to map a subset of input channel range
730: * into a subset of the output channel range
731: */
732: void
733: cmap_init(struct cmap *p,
734: int imin, int imax, int isubmin, int isubmax,
735: int omin, int omax, int osubmin, int osubmax)
736: {
737: int cmin, cmax;
738:
739: cmin = -NCHAN_MAX;
740: if (osubmin > cmin)
741: cmin = osubmin;
742: if (omin > cmin)
743: cmin = omin;
744: if (isubmin > cmin)
745: cmin = isubmin;
746: if (imin > cmin)
747: cmin = imin;
748:
749: cmax = NCHAN_MAX;
750: if (osubmax < cmax)
751: cmax = osubmax;
752: if (omax < cmax)
753: cmax = omax;
754: if (isubmax < cmax)
755: cmax = isubmax;
756: if (imax < cmax)
757: cmax = imax;
758:
759: p->ostart = cmin - omin;
760: p->onext = omax - cmax;
761: p->istart = cmin - imin;
762: p->inext = imax - cmax;
763: p->nch = cmax - cmin + 1;
764: #ifdef DEBUG
765: if (log_level >= 3) {
766: log_puts("cmap: nch = ");
767: log_puti(p->nch);
768: log_puts(", ostart = ");
769: log_puti(p->ostart);
770: log_puts(", onext = ");
771: log_puti(p->onext);
772: log_puts(", istart = ");
773: log_puti(p->istart);
1.6 ratchov 774: log_puts(", inext = ");
1.1 ratchov 775: log_puti(p->inext);
776: log_puts("\n");
777: }
778: #endif
779: }