1 /* $OpenBSD: dsp.c,v 1.17 2021/01/12 15:46:53 naddy Exp $ */ 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 21 const int aparams_ctltovol[128] = { 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 41 const int resamp_filt[RESAMP_LENGTH / RESAMP_STEP + 1] = { 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 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 /* 208 * get (optional) alignment 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: 224 par->msb = msb; 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 { 264 return par->sig && 265 par->bps == sizeof(adata_t) && 266 par->bits == ADATA_BITS && 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 */ 274 void 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; 284 int64_t f[NCHAN_MAX]; 285 adata_t *ctxbuf, *ctx; 286 unsigned int ctx_start; 287 int q, qi, qf, n; 288 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 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; 303 diff = p->oblksz; 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 (;;) { 311 if (diff >= oblksz) { 312 if (todo == 0) 313 break; 314 ctx_start = (ctx_start - 1) & (RESAMP_NCTX - 1); 315 ctx = ctxbuf + ctx_start; 316 for (c = nch; c > 0; c--) { 317 *ctx = *idata++; 318 ctx += RESAMP_NCTX; 319 } 320 diff -= oblksz; 321 todo--; 322 } else { 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 345 for (c = nch; c > 0; c--) { 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; 363 } 364 diff += iblksz; 365 } 366 } 367 368 p->ctx_start = ctx_start; 369 } 370 371 /* 372 * initialize resampler with ibufsz/obufsz factor and "nch" channels 373 */ 374 void 375 resamp_init(struct resamp *p, unsigned int iblksz, 376 unsigned int oblksz, int nch) 377 { 378 p->iblksz = iblksz; 379 p->oblksz = oblksz; 380 p->nch = nch; 381 p->ctx_start = 0; 382 memset(p->ctx, 0, sizeof(p->ctx)); 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 } 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; 409 unsigned int s; 410 unsigned int oshift; 411 unsigned int obias; 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; 433 obias = p->bias; 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--) { 443 /* convert adata to u32 */ 444 s = (int)*idata++ + ADATA_UNIT; 445 s <<= 32 - ADATA_BITS; 446 /* convert u32 to uN */ 447 s >>= oshift; 448 /* convert uN to sN */ 449 s -= obias; 450 /* packetize sN */ 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; 467 unsigned int s; 468 unsigned int oshift; 469 int obias; 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; 489 oshift = p->shift; 490 obias = p->bias; 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--) { 500 s = ((1U << 31) >> oshift) - obias; 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 } 523 if (par->sig) { 524 p->bias = (1U << 31) >> p->shift; 525 } else { 526 p->bias = 0; 527 } 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 /* 549 * decode "todo" frames from foreign to native encoding 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; 557 unsigned int s = 0xdeadbeef; 558 unsigned char *idata; 559 int ibnext; 560 int isnext; 561 unsigned int ibias; 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; 581 ibias = p->bias; 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; 596 s += ibias; 597 s <<= ishift; 598 s >>= 32 - ADATA_BITS; 599 *odata++ = s - ADATA_UNIT; 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 } 616 if (par->sig) { 617 p->bias = (1U << 31) >> p->shift; 618 } else { 619 p->bias = 0; 620 } 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; 664 v = vol; 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 /* 688 * overwrite output with "todo" input frames with the given volume 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; 717 odata += ostart; 718 for (j = nch; j > 0; j--) { 719 *odata = ADATA_MUL(*idata, v); 720 odata++; 721 idata++; 722 } 723 odata += onext; 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); 774 log_puts(", inext = "); 775 log_puti(p->inext); 776 log_puts("\n"); 777 } 778 #endif 779 } 780