1*b4d5e3c9Sratchov /* $OpenBSD: dsp.c,v 1.21 2024/12/22 14:17:45 ratchov Exp $ */ 210ba9548Sratchov /* 310ba9548Sratchov * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> 410ba9548Sratchov * 510ba9548Sratchov * Permission to use, copy, modify, and distribute this software for any 610ba9548Sratchov * purpose with or without fee is hereby granted, provided that the above 710ba9548Sratchov * copyright notice and this permission notice appear in all copies. 810ba9548Sratchov * 910ba9548Sratchov * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1010ba9548Sratchov * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1110ba9548Sratchov * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1210ba9548Sratchov * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1310ba9548Sratchov * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1410ba9548Sratchov * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1510ba9548Sratchov * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1610ba9548Sratchov */ 173848b6b4Smiko #include <string.h> 1810ba9548Sratchov #include "dsp.h" 1910ba9548Sratchov #include "utils.h" 2010ba9548Sratchov 21b020cfe1Snaddy const int aparams_ctltovol[128] = { 227a7aa84cSratchov 0, 65536, 68109, 70783, 237a7aa84cSratchov 73562, 76450, 79451, 82570, 247a7aa84cSratchov 85812, 89181, 92682, 96321, 257a7aa84cSratchov 100102, 104032, 108116, 112361, 267a7aa84cSratchov 116772, 121356, 126121, 131072, 277a7aa84cSratchov 136218, 141566, 147123, 152899, 287a7aa84cSratchov 158902, 165140, 171624, 178361, 297a7aa84cSratchov 185364, 192641, 200204, 208064, 307a7aa84cSratchov 216232, 224721, 233544, 242713, 317a7aa84cSratchov 252241, 262144, 272436, 283131, 327a7aa84cSratchov 294247, 305799, 317804, 330281, 337a7aa84cSratchov 343247, 356723, 370728, 385282, 347a7aa84cSratchov 400408, 416128, 432465, 449443, 357a7aa84cSratchov 467088, 485425, 504482, 524288, 367a7aa84cSratchov 544871, 566262, 588493, 611597, 377a7aa84cSratchov 635608, 660561, 686495, 713446, 387a7aa84cSratchov 741455, 770564, 800816, 832255, 397a7aa84cSratchov 864929, 898885, 934175, 970850, 407a7aa84cSratchov 1008965, 1048576, 1089742, 1132525, 417a7aa84cSratchov 1176987, 1223194, 1271216, 1321123, 427a7aa84cSratchov 1372989, 1426892, 1482910, 1541128, 437a7aa84cSratchov 1601632, 1664511, 1729858, 1797771, 447a7aa84cSratchov 1868350, 1941700, 2017930, 2097152, 457a7aa84cSratchov 2179485, 2265049, 2353974, 2446389, 467a7aa84cSratchov 2542432, 2642246, 2745978, 2853783, 477a7aa84cSratchov 2965821, 3082257, 3203264, 3329021, 487a7aa84cSratchov 3459716, 3595542, 3736700, 3883400, 497a7aa84cSratchov 4035859, 4194304, 4358969, 4530099, 507a7aa84cSratchov 4707947, 4892777, 5084864, 5284492, 517a7aa84cSratchov 5491957, 5707567, 5931642, 6164513, 527a7aa84cSratchov 6406527, 6658043, 6919432, 7191084, 537a7aa84cSratchov 7473400, 7766800, 8071719, 8388608 5410ba9548Sratchov }; 5510ba9548Sratchov 56b020cfe1Snaddy const short dec_ulawmap[256] = { 5710ba9548Sratchov -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, 5810ba9548Sratchov -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, 5910ba9548Sratchov -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, 6010ba9548Sratchov -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, 6110ba9548Sratchov -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, 6210ba9548Sratchov -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, 6310ba9548Sratchov -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, 6410ba9548Sratchov -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, 6510ba9548Sratchov -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, 6610ba9548Sratchov -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, 6710ba9548Sratchov -876, -844, -812, -780, -748, -716, -684, -652, 6810ba9548Sratchov -620, -588, -556, -524, -492, -460, -428, -396, 6910ba9548Sratchov -372, -356, -340, -324, -308, -292, -276, -260, 7010ba9548Sratchov -244, -228, -212, -196, -180, -164, -148, -132, 7110ba9548Sratchov -120, -112, -104, -96, -88, -80, -72, -64, 7210ba9548Sratchov -56, -48, -40, -32, -24, -16, -8, 0, 7310ba9548Sratchov 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 7410ba9548Sratchov 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 7510ba9548Sratchov 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 7610ba9548Sratchov 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7710ba9548Sratchov 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 7810ba9548Sratchov 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 7910ba9548Sratchov 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 8010ba9548Sratchov 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 8110ba9548Sratchov 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 8210ba9548Sratchov 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 8310ba9548Sratchov 876, 844, 812, 780, 748, 716, 684, 652, 8410ba9548Sratchov 620, 588, 556, 524, 492, 460, 428, 396, 8510ba9548Sratchov 372, 356, 340, 324, 308, 292, 276, 260, 8610ba9548Sratchov 244, 228, 212, 196, 180, 164, 148, 132, 8710ba9548Sratchov 120, 112, 104, 96, 88, 80, 72, 64, 8810ba9548Sratchov 56, 48, 40, 32, 24, 16, 8, 0 8910ba9548Sratchov }; 9010ba9548Sratchov 91b020cfe1Snaddy const short dec_alawmap[256] = { 9210ba9548Sratchov -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, 9310ba9548Sratchov -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, 9410ba9548Sratchov -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, 9510ba9548Sratchov -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, 9610ba9548Sratchov -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, 9710ba9548Sratchov -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, 9810ba9548Sratchov -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, 9910ba9548Sratchov -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, 10010ba9548Sratchov -344, -328, -376, -360, -280, -264, -312, -296, 10110ba9548Sratchov -472, -456, -504, -488, -408, -392, -440, -424, 10210ba9548Sratchov -88, -72, -120, -104, -24, -8, -56, -40, 10310ba9548Sratchov -216, -200, -248, -232, -152, -136, -184, -168, 10410ba9548Sratchov -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, 10510ba9548Sratchov -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, 10610ba9548Sratchov -688, -656, -752, -720, -560, -528, -624, -592, 10710ba9548Sratchov -944, -912, -1008, -976, -816, -784, -880, -848, 10810ba9548Sratchov 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 10910ba9548Sratchov 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 11010ba9548Sratchov 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 11110ba9548Sratchov 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 11210ba9548Sratchov 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 11310ba9548Sratchov 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11410ba9548Sratchov 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 11510ba9548Sratchov 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 11610ba9548Sratchov 344, 328, 376, 360, 280, 264, 312, 296, 11710ba9548Sratchov 472, 456, 504, 488, 408, 392, 440, 424, 11810ba9548Sratchov 88, 72, 120, 104, 24, 8, 56, 40, 11910ba9548Sratchov 216, 200, 248, 232, 152, 136, 184, 168, 12010ba9548Sratchov 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 12110ba9548Sratchov 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 12210ba9548Sratchov 688, 656, 752, 720, 560, 528, 624, 592, 12310ba9548Sratchov 944, 912, 1008, 976, 816, 784, 880, 848 12410ba9548Sratchov }; 12510ba9548Sratchov 126b020cfe1Snaddy const int resamp_filt[RESAMP_LENGTH / RESAMP_STEP + 1] = { 127da5bcb9fSratchov 0, 0, 3, 9, 22, 42, 73, 116, 128da5bcb9fSratchov 174, 248, 341, 454, 589, 749, 934, 1148, 129da5bcb9fSratchov 1392, 1666, 1974, 2316, 2693, 3107, 3560, 4051, 130da5bcb9fSratchov 4582, 5154, 5766, 6420, 7116, 7853, 8632, 9451, 131da5bcb9fSratchov 10311, 11210, 12148, 13123, 14133, 15178, 16253, 17359, 132da5bcb9fSratchov 18491, 19647, 20824, 22018, 23226, 24443, 25665, 26888, 133da5bcb9fSratchov 28106, 29315, 30509, 31681, 32826, 33938, 35009, 36033, 134da5bcb9fSratchov 37001, 37908, 38744, 39502, 40174, 40750, 41223, 41582, 135da5bcb9fSratchov 41819, 41925, 41890, 41704, 41358, 40842, 40147, 39261, 136da5bcb9fSratchov 38176, 36881, 35366, 33623, 31641, 29411, 26923, 24169, 137da5bcb9fSratchov 21140, 17827, 14222, 10317, 6105, 1580, -3267, -8440, 138da5bcb9fSratchov -13944, -19785, -25967, -32492, -39364, -46584, -54153, -62072, 139da5bcb9fSratchov -70339, -78953, -87911, -97209, -106843, -116806, -127092, -137692, 140da5bcb9fSratchov -148596, -159795, -171276, -183025, -195029, -207271, -219735, -232401, 141da5bcb9fSratchov -245249, -258259, -271407, -284670, -298021, -311434, -324880, -338329, 142da5bcb9fSratchov -351750, -365111, -378378, -391515, -404485, -417252, -429775, -442015, 143da5bcb9fSratchov -453930, -465477, -476613, -487294, -497472, -507102, -516137, -524527, 144da5bcb9fSratchov -532225, -539181, -545344, -550664, -555090, -558571, -561055, -562490, 145da5bcb9fSratchov -562826, -562010, -559990, -556717, -552139, -546205, -538866, -530074, 146da5bcb9fSratchov -519779, -507936, -494496, -479416, -462652, -444160, -423901, -401835, 147da5bcb9fSratchov -377923, -352132, -324425, -294772, -263143, -229509, -193847, -156134, 148da5bcb9fSratchov -116348, -74474, -30494, 15601, 63822, 114174, 166661, 221283, 149da5bcb9fSratchov 278037, 336916, 397911, 461009, 526194, 593446, 662741, 734054, 150da5bcb9fSratchov 807354, 882608, 959779, 1038826, 1119706, 1202370, 1286768, 1372846, 151da5bcb9fSratchov 1460546, 1549808, 1640566, 1732753, 1826299, 1921130, 2017169, 2114336, 152da5bcb9fSratchov 2212550, 2311723, 2411770, 2512598, 2614116, 2716228, 2818836, 2921841, 153da5bcb9fSratchov 3025142, 3128636, 3232218, 3335782, 3439219, 3542423, 3645282, 3747687, 154da5bcb9fSratchov 3849526, 3950687, 4051059, 4150530, 4248987, 4346320, 4442415, 4537163, 155da5bcb9fSratchov 4630453, 4722177, 4812225, 4900493, 4986873, 5071263, 5153561, 5233668, 156da5bcb9fSratchov 5311485, 5386917, 5459872, 5530259, 5597992, 5662986, 5725160, 5784436, 157da5bcb9fSratchov 5840739, 5893999, 5944148, 5991122, 6034862, 6075313, 6112422, 6146142, 158da5bcb9fSratchov 6176430, 6203247, 6226559, 6246335, 6262551, 6275185, 6284220, 6289647, 159da5bcb9fSratchov 6291456, 6289647, 6284220, 6275185, 6262551, 6246335, 6226559, 6203247, 160da5bcb9fSratchov 6176430, 6146142, 6112422, 6075313, 6034862, 5991122, 5944148, 5893999, 161da5bcb9fSratchov 5840739, 5784436, 5725160, 5662986, 5597992, 5530259, 5459872, 5386917, 162da5bcb9fSratchov 5311485, 5233668, 5153561, 5071263, 4986873, 4900493, 4812225, 4722177, 163da5bcb9fSratchov 4630453, 4537163, 4442415, 4346320, 4248987, 4150530, 4051059, 3950687, 164da5bcb9fSratchov 3849526, 3747687, 3645282, 3542423, 3439219, 3335782, 3232218, 3128636, 165da5bcb9fSratchov 3025142, 2921841, 2818836, 2716228, 2614116, 2512598, 2411770, 2311723, 166da5bcb9fSratchov 2212550, 2114336, 2017169, 1921130, 1826299, 1732753, 1640566, 1549808, 167da5bcb9fSratchov 1460546, 1372846, 1286768, 1202370, 1119706, 1038826, 959779, 882608, 168da5bcb9fSratchov 807354, 734054, 662741, 593446, 526194, 461009, 397911, 336916, 169da5bcb9fSratchov 278037, 221283, 166661, 114174, 63822, 15601, -30494, -74474, 170da5bcb9fSratchov -116348, -156134, -193847, -229509, -263143, -294772, -324425, -352132, 171da5bcb9fSratchov -377923, -401835, -423901, -444160, -462652, -479416, -494496, -507936, 172da5bcb9fSratchov -519779, -530074, -538866, -546205, -552139, -556717, -559990, -562010, 173da5bcb9fSratchov -562826, -562490, -561055, -558571, -555090, -550664, -545344, -539181, 174da5bcb9fSratchov -532225, -524527, -516137, -507102, -497472, -487294, -476613, -465477, 175da5bcb9fSratchov -453930, -442015, -429775, -417252, -404485, -391515, -378378, -365111, 176da5bcb9fSratchov -351750, -338329, -324880, -311434, -298021, -284670, -271407, -258259, 177da5bcb9fSratchov -245249, -232401, -219735, -207271, -195029, -183025, -171276, -159795, 178da5bcb9fSratchov -148596, -137692, -127092, -116806, -106843, -97209, -87911, -78953, 179da5bcb9fSratchov -70339, -62072, -54153, -46584, -39364, -32492, -25967, -19785, 180da5bcb9fSratchov -13944, -8440, -3267, 1580, 6105, 10317, 14222, 17827, 181da5bcb9fSratchov 21140, 24169, 26923, 29411, 31641, 33623, 35366, 36881, 182da5bcb9fSratchov 38176, 39261, 40147, 40842, 41358, 41704, 41890, 41925, 183da5bcb9fSratchov 41819, 41582, 41223, 40750, 40174, 39502, 38744, 37908, 184da5bcb9fSratchov 37001, 36033, 35009, 33938, 32826, 31681, 30509, 29315, 185da5bcb9fSratchov 28106, 26888, 25665, 24443, 23226, 22018, 20824, 19647, 186da5bcb9fSratchov 18491, 17359, 16253, 15178, 14133, 13123, 12148, 11210, 187da5bcb9fSratchov 10311, 9451, 8632, 7853, 7116, 6420, 5766, 5154, 188da5bcb9fSratchov 4582, 4051, 3560, 3107, 2693, 2316, 1974, 1666, 189da5bcb9fSratchov 1392, 1148, 934, 749, 589, 454, 341, 248, 190da5bcb9fSratchov 174, 116, 73, 42, 22, 9, 3, 0, 191da5bcb9fSratchov 0 192da5bcb9fSratchov }; 193da5bcb9fSratchov 194da5bcb9fSratchov 19510ba9548Sratchov /* 19610ba9548Sratchov * Generate a string corresponding to the encoding in par, 19710ba9548Sratchov * return the length of the resulting string. 19810ba9548Sratchov */ 19910ba9548Sratchov int 20010ba9548Sratchov aparams_enctostr(struct aparams *par, char *ostr) 20110ba9548Sratchov { 20210ba9548Sratchov char *p = ostr; 20310ba9548Sratchov 20410ba9548Sratchov *p++ = par->sig ? 's' : 'u'; 20510ba9548Sratchov if (par->bits > 9) 20610ba9548Sratchov *p++ = '0' + par->bits / 10; 20710ba9548Sratchov *p++ = '0' + par->bits % 10; 20810ba9548Sratchov if (par->bps > 1) { 20910ba9548Sratchov *p++ = par->le ? 'l' : 'b'; 21010ba9548Sratchov *p++ = 'e'; 21110ba9548Sratchov if (par->bps != APARAMS_BPS(par->bits) || 21210ba9548Sratchov par->bits < par->bps * 8) { 21310ba9548Sratchov *p++ = par->bps + '0'; 21410ba9548Sratchov if (par->bits < par->bps * 8) { 21510ba9548Sratchov *p++ = par->msb ? 'm' : 'l'; 21610ba9548Sratchov *p++ = 's'; 21710ba9548Sratchov *p++ = 'b'; 21810ba9548Sratchov } 21910ba9548Sratchov } 22010ba9548Sratchov } 22110ba9548Sratchov *p++ = '\0'; 22210ba9548Sratchov return p - ostr - 1; 22310ba9548Sratchov } 22410ba9548Sratchov 22510ba9548Sratchov /* 22610ba9548Sratchov * Parse an encoding string, examples: s8, u8, s16, s16le, s24be ... 22710ba9548Sratchov * set *istr to the char following the encoding. Return the number 22810ba9548Sratchov * of bytes consumed. 22910ba9548Sratchov */ 23010ba9548Sratchov int 23110ba9548Sratchov aparams_strtoenc(struct aparams *par, char *istr) 23210ba9548Sratchov { 23310ba9548Sratchov char *p = istr; 23410ba9548Sratchov int i, sig, bits, le, bps, msb; 23510ba9548Sratchov 23610ba9548Sratchov #define IS_SEP(c) \ 23710ba9548Sratchov (((c) < 'a' || (c) > 'z') && \ 23810ba9548Sratchov ((c) < 'A' || (c) > 'Z') && \ 23910ba9548Sratchov ((c) < '0' || (c) > '9')) 24010ba9548Sratchov 24110ba9548Sratchov /* 24210ba9548Sratchov * get signedness 24310ba9548Sratchov */ 24410ba9548Sratchov if (*p == 's') { 24510ba9548Sratchov sig = 1; 24610ba9548Sratchov } else if (*p == 'u') { 24710ba9548Sratchov sig = 0; 24810ba9548Sratchov } else 24910ba9548Sratchov return 0; 25010ba9548Sratchov p++; 25110ba9548Sratchov 25210ba9548Sratchov /* 25310ba9548Sratchov * get number of bits per sample 25410ba9548Sratchov */ 25510ba9548Sratchov bits = 0; 25610ba9548Sratchov for (i = 0; i < 2; i++) { 25710ba9548Sratchov if (*p < '0' || *p > '9') 25810ba9548Sratchov break; 25910ba9548Sratchov bits = (bits * 10) + *p - '0'; 26010ba9548Sratchov p++; 26110ba9548Sratchov } 26210ba9548Sratchov if (bits < BITS_MIN || bits > BITS_MAX) 26310ba9548Sratchov return 0; 26410ba9548Sratchov bps = APARAMS_BPS(bits); 26510ba9548Sratchov msb = 1; 26610ba9548Sratchov le = ADATA_LE; 26710ba9548Sratchov 26810ba9548Sratchov /* 26910ba9548Sratchov * get (optional) endianness 27010ba9548Sratchov */ 27110ba9548Sratchov if (p[0] == 'l' && p[1] == 'e') { 27210ba9548Sratchov le = 1; 27310ba9548Sratchov p += 2; 27410ba9548Sratchov } else if (p[0] == 'b' && p[1] == 'e') { 27510ba9548Sratchov le = 0; 27610ba9548Sratchov p += 2; 27710ba9548Sratchov } else if (IS_SEP(*p)) { 27810ba9548Sratchov goto done; 27910ba9548Sratchov } else 28010ba9548Sratchov return 0; 28110ba9548Sratchov 28210ba9548Sratchov /* 28310ba9548Sratchov * get (optional) number of bytes 28410ba9548Sratchov */ 28510ba9548Sratchov if (*p >= '0' && *p <= '9') { 28610ba9548Sratchov bps = *p - '0'; 28710ba9548Sratchov if (bps < (bits + 7) / 8 || 28810ba9548Sratchov bps > (BITS_MAX + 7) / 8) 28910ba9548Sratchov return 0; 29010ba9548Sratchov p++; 29110ba9548Sratchov 29210ba9548Sratchov /* 29310ba9548Sratchov * get (optional) alignment 29410ba9548Sratchov */ 29510ba9548Sratchov if (p[0] == 'm' && p[1] == 's' && p[2] == 'b') { 29610ba9548Sratchov msb = 1; 29710ba9548Sratchov p += 3; 29810ba9548Sratchov } else if (p[0] == 'l' && p[1] == 's' && p[2] == 'b') { 29910ba9548Sratchov msb = 0; 30010ba9548Sratchov p += 3; 30110ba9548Sratchov } else if (IS_SEP(*p)) { 30210ba9548Sratchov goto done; 30310ba9548Sratchov } else 30410ba9548Sratchov return 0; 30510ba9548Sratchov } else if (!IS_SEP(*p)) 30610ba9548Sratchov return 0; 30710ba9548Sratchov 30810ba9548Sratchov done: 30910ba9548Sratchov par->msb = msb; 31010ba9548Sratchov par->sig = sig; 31110ba9548Sratchov par->bits = bits; 31210ba9548Sratchov par->bps = bps; 31310ba9548Sratchov par->le = le; 31410ba9548Sratchov return p - istr; 31510ba9548Sratchov } 31610ba9548Sratchov 31710ba9548Sratchov /* 31810ba9548Sratchov * Initialise parameters structure with the defaults natively supported 31910ba9548Sratchov * by the machine. 32010ba9548Sratchov */ 32110ba9548Sratchov void 32210ba9548Sratchov aparams_init(struct aparams *par) 32310ba9548Sratchov { 32410ba9548Sratchov par->bps = sizeof(adata_t); 32510ba9548Sratchov par->bits = ADATA_BITS; 32610ba9548Sratchov par->le = ADATA_LE; 32710ba9548Sratchov par->sig = 1; 32810ba9548Sratchov par->msb = 0; 32910ba9548Sratchov } 33010ba9548Sratchov 33110ba9548Sratchov /* 33210ba9548Sratchov * return true if encoding corresponds to what we store in adata_t 33310ba9548Sratchov */ 33410ba9548Sratchov int 33510ba9548Sratchov aparams_native(struct aparams *par) 33610ba9548Sratchov { 3371852f103Sratchov return par->sig && 3381852f103Sratchov par->bps == sizeof(adata_t) && 3391852f103Sratchov par->bits == ADATA_BITS && 34010ba9548Sratchov (par->bps == 1 || par->le == ADATA_LE) && 34110ba9548Sratchov (par->bits == par->bps * 8 || !par->msb); 34210ba9548Sratchov } 34310ba9548Sratchov 34410ba9548Sratchov /* 345e215e383Sratchov * Return the number of input and output frame that would be consumed 346e215e383Sratchov * by resamp_do(p, *icnt, *ocnt). 347bac75139Sratchov */ 3481f1e15b4Sratchov void 3491f1e15b4Sratchov resamp_getcnt(struct resamp *p, int *icnt, int *ocnt) 350bac75139Sratchov { 351e215e383Sratchov long long idiff, odiff; 352e215e383Sratchov int cdiff; 353bac75139Sratchov 354e215e383Sratchov cdiff = p->oblksz - p->diff; 355e215e383Sratchov idiff = (long long)*icnt * p->oblksz; 356e215e383Sratchov odiff = (long long)*ocnt * p->iblksz; 357e215e383Sratchov if (odiff - idiff >= cdiff) 358e215e383Sratchov *ocnt = (idiff + cdiff + p->iblksz - 1) / p->iblksz; 359e215e383Sratchov else 360e215e383Sratchov *icnt = (odiff + p->diff) / p->oblksz; 361bac75139Sratchov } 362bac75139Sratchov 363bac75139Sratchov /* 364bac75139Sratchov * Resample the given number of frames. The number of output frames 365d9a51c35Sjmc * must match the corresponding number of input frames. Either always 3661f1e15b4Sratchov * use icnt and ocnt such that: 367bac75139Sratchov * 3681f1e15b4Sratchov * icnt * oblksz = ocnt * iblksz 369bac75139Sratchov * 3701f1e15b4Sratchov * or use resamp_getcnt() to calculate the proper numbers. 37110ba9548Sratchov */ 3722e3cf7c1Sratchov void 373bac75139Sratchov resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) 37410ba9548Sratchov { 37510ba9548Sratchov unsigned int nch; 37610ba9548Sratchov adata_t *idata; 37710ba9548Sratchov unsigned int oblksz; 37810ba9548Sratchov unsigned int ifr; 37910ba9548Sratchov int s, ds, diff; 38010ba9548Sratchov adata_t *odata; 38110ba9548Sratchov unsigned int iblksz; 38210ba9548Sratchov unsigned int ofr; 38310ba9548Sratchov unsigned int c; 384da5bcb9fSratchov int64_t f[NCHAN_MAX]; 38510ba9548Sratchov adata_t *ctxbuf, *ctx; 38610ba9548Sratchov unsigned int ctx_start; 387da5bcb9fSratchov int q, qi, qf, n; 38810ba9548Sratchov 38910ba9548Sratchov /* 39010ba9548Sratchov * Partially copy structures into local variables, to avoid 39110ba9548Sratchov * unnecessary indirections; this also allows the compiler to 39210ba9548Sratchov * order local variables more "cache-friendly". 39310ba9548Sratchov */ 39410ba9548Sratchov idata = in; 39510ba9548Sratchov odata = out; 39610ba9548Sratchov diff = p->diff; 39710ba9548Sratchov iblksz = p->iblksz; 39810ba9548Sratchov oblksz = p->oblksz; 39910ba9548Sratchov ctxbuf = p->ctx; 40010ba9548Sratchov ctx_start = p->ctx_start; 40110ba9548Sratchov nch = p->nch; 402bac75139Sratchov ifr = icnt; 403bac75139Sratchov ofr = ocnt; 40410ba9548Sratchov 40510ba9548Sratchov /* 40610ba9548Sratchov * Start conversion. 40710ba9548Sratchov */ 40810ba9548Sratchov #ifdef DEBUG 409*b4d5e3c9Sratchov logx(4, "resamp: copying %d -> %d frames, diff = %d", ifr, ofr, diff); 41010ba9548Sratchov #endif 41110ba9548Sratchov for (;;) { 412e215e383Sratchov if (diff >= oblksz) { 41310ba9548Sratchov if (ifr == 0) 41410ba9548Sratchov break; 415da5bcb9fSratchov ctx_start = (ctx_start - 1) & (RESAMP_NCTX - 1); 41610ba9548Sratchov ctx = ctxbuf + ctx_start; 41710ba9548Sratchov for (c = nch; c > 0; c--) { 41810ba9548Sratchov *ctx = *idata++; 41910ba9548Sratchov ctx += RESAMP_NCTX; 42010ba9548Sratchov } 421e215e383Sratchov diff -= oblksz; 42210ba9548Sratchov ifr--; 423e215e383Sratchov } else { 42410ba9548Sratchov if (ofr == 0) 42510ba9548Sratchov break; 426da5bcb9fSratchov 42732ba4c83Sratchov for (c = 0; c < nch; c++) 428da5bcb9fSratchov f[c] = 0; 429da5bcb9fSratchov 430da5bcb9fSratchov q = diff * p->filt_step; 431da5bcb9fSratchov n = ctx_start; 432da5bcb9fSratchov 433da5bcb9fSratchov while (q < RESAMP_LENGTH) { 434da5bcb9fSratchov qi = q >> RESAMP_STEP_BITS; 435da5bcb9fSratchov qf = q & (RESAMP_STEP - 1); 436da5bcb9fSratchov s = resamp_filt[qi]; 437da5bcb9fSratchov ds = resamp_filt[qi + 1] - s; 438da5bcb9fSratchov s += (int64_t)qf * ds >> RESAMP_STEP_BITS; 43910ba9548Sratchov ctx = ctxbuf; 44032ba4c83Sratchov for (c = 0; c < nch; c++) { 441da5bcb9fSratchov f[c] += (int64_t)ctx[n] * s; 44210ba9548Sratchov ctx += RESAMP_NCTX; 44310ba9548Sratchov } 444da5bcb9fSratchov q += p->filt_cutoff; 445da5bcb9fSratchov n = (n + 1) & (RESAMP_NCTX - 1); 446da5bcb9fSratchov } 447da5bcb9fSratchov 44832ba4c83Sratchov for (c = 0; c < nch; c++) { 449da5bcb9fSratchov s = f[c] >> RESAMP_BITS; 450da5bcb9fSratchov s = (int64_t)s * p->filt_cutoff >> RESAMP_BITS; 451da5bcb9fSratchov #if ADATA_BITS == 16 452da5bcb9fSratchov /* 453da5bcb9fSratchov * In 16-bit mode, we've no room for filter 454da5bcb9fSratchov * overshoots, so we need to clip the signal 455da5bcb9fSratchov * to avoid 16-bit integers to wrap around. 456da5bcb9fSratchov * In 24-bit mode, samples may exceed the 457da5bcb9fSratchov * [-1:1] range. Later, cmap_add() will clip 458da5bcb9fSratchov * them, so no need to clip them here as well. 459da5bcb9fSratchov */ 460da5bcb9fSratchov if (s >= ADATA_UNIT) 461da5bcb9fSratchov s = ADATA_UNIT - 1; 462da5bcb9fSratchov else if (s < -ADATA_UNIT) 463da5bcb9fSratchov s = -ADATA_UNIT; 464da5bcb9fSratchov #endif 465da5bcb9fSratchov *odata++ = s; 466da5bcb9fSratchov } 467da5bcb9fSratchov 468e215e383Sratchov diff += iblksz; 46910ba9548Sratchov ofr--; 47010ba9548Sratchov } 47110ba9548Sratchov } 47210ba9548Sratchov p->diff = diff; 47310ba9548Sratchov p->ctx_start = ctx_start; 474bac75139Sratchov #ifdef DEBUG 475bac75139Sratchov if (ifr != 0) { 476*b4d5e3c9Sratchov logx(0, "resamp_do: %d: too many input frames", ifr); 477bac75139Sratchov panic(); 478bac75139Sratchov } 479bac75139Sratchov if (ofr != 0) { 480*b4d5e3c9Sratchov logx(0, "resamp_do: %d: too many output frames", ofr); 481bac75139Sratchov panic(); 482bac75139Sratchov } 483bac75139Sratchov #endif 48410ba9548Sratchov } 48510ba9548Sratchov 486f2e307d4Sratchov static unsigned int 487f2e307d4Sratchov uint_gcd(unsigned int a, unsigned int b) 488f2e307d4Sratchov { 489f2e307d4Sratchov unsigned int r; 490f2e307d4Sratchov 491f2e307d4Sratchov while (b > 0) { 492f2e307d4Sratchov r = a % b; 493f2e307d4Sratchov a = b; 494f2e307d4Sratchov b = r; 495f2e307d4Sratchov } 496f2e307d4Sratchov return a; 497f2e307d4Sratchov } 498f2e307d4Sratchov 49910ba9548Sratchov /* 50010ba9548Sratchov * initialize resampler with ibufsz/obufsz factor and "nch" channels 50110ba9548Sratchov */ 50210ba9548Sratchov void 5033d938fd4Sratchov resamp_init(struct resamp *p, unsigned int iblksz, 5043d938fd4Sratchov unsigned int oblksz, int nch) 50510ba9548Sratchov { 5063848b6b4Smiko unsigned int g; 507f2e307d4Sratchov 508f2e307d4Sratchov /* 509bbe3c388Sratchov * reduce iblksz/oblksz fraction 510f2e307d4Sratchov */ 511f2e307d4Sratchov g = uint_gcd(iblksz, oblksz); 512f2e307d4Sratchov iblksz /= g; 513f2e307d4Sratchov oblksz /= g; 514f2e307d4Sratchov 515f2e307d4Sratchov /* 516bbe3c388Sratchov * ensure weird rates don't cause integer overflow 517f2e307d4Sratchov */ 518f2e307d4Sratchov while (iblksz > ADATA_UNIT || oblksz > ADATA_UNIT) { 519f2e307d4Sratchov iblksz >>= 1; 520f2e307d4Sratchov oblksz >>= 1; 521f2e307d4Sratchov } 52210ba9548Sratchov 52310ba9548Sratchov p->iblksz = iblksz; 52410ba9548Sratchov p->oblksz = oblksz; 52510ba9548Sratchov p->diff = 0; 52610ba9548Sratchov p->nch = nch; 52710ba9548Sratchov p->ctx_start = 0; 5283848b6b4Smiko memset(p->ctx, 0, sizeof(p->ctx)); 529da5bcb9fSratchov if (p->iblksz < p->oblksz) { 530da5bcb9fSratchov p->filt_cutoff = RESAMP_UNIT; 531da5bcb9fSratchov p->filt_step = RESAMP_UNIT / p->oblksz; 532da5bcb9fSratchov } else { 533da5bcb9fSratchov p->filt_cutoff = (int64_t)RESAMP_UNIT * p->oblksz / p->iblksz; 534da5bcb9fSratchov p->filt_step = RESAMP_UNIT / p->iblksz; 535da5bcb9fSratchov } 53610ba9548Sratchov #ifdef DEBUG 537*b4d5e3c9Sratchov logx(3, "resamp_init: %u/%u", iblksz, oblksz); 53810ba9548Sratchov #endif 53910ba9548Sratchov } 54010ba9548Sratchov 54110ba9548Sratchov /* 54210ba9548Sratchov * encode "todo" frames from native to foreign encoding 54310ba9548Sratchov */ 54410ba9548Sratchov void 54510ba9548Sratchov enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) 54610ba9548Sratchov { 54710ba9548Sratchov unsigned int f; 54810ba9548Sratchov adata_t *idata; 54910ba9548Sratchov unsigned int s; 55010ba9548Sratchov unsigned int oshift; 55110ba9548Sratchov unsigned int obias; 55210ba9548Sratchov unsigned int obps; 55310ba9548Sratchov unsigned int i; 55410ba9548Sratchov unsigned char *odata; 55510ba9548Sratchov int obnext; 55610ba9548Sratchov int osnext; 55710ba9548Sratchov 55810ba9548Sratchov #ifdef DEBUG 559*b4d5e3c9Sratchov logx(4, "enc: copying %u frames", todo); 56010ba9548Sratchov #endif 56110ba9548Sratchov /* 56210ba9548Sratchov * Partially copy structures into local variables, to avoid 56310ba9548Sratchov * unnecessary indirections; this also allows the compiler to 56410ba9548Sratchov * order local variables more "cache-friendly". 56510ba9548Sratchov */ 56610ba9548Sratchov idata = (adata_t *)in; 56710ba9548Sratchov odata = out; 56810ba9548Sratchov oshift = p->shift; 56910ba9548Sratchov obias = p->bias; 57010ba9548Sratchov obps = p->bps; 57110ba9548Sratchov obnext = p->bnext; 57210ba9548Sratchov osnext = p->snext; 57310ba9548Sratchov 57410ba9548Sratchov /* 57510ba9548Sratchov * Start conversion. 57610ba9548Sratchov */ 57710ba9548Sratchov odata += p->bfirst; 57810ba9548Sratchov for (f = todo * p->nch; f > 0; f--) { 57910ba9548Sratchov /* convert adata to u32 */ 58010ba9548Sratchov s = (int)*idata++ + ADATA_UNIT; 58110ba9548Sratchov s <<= 32 - ADATA_BITS; 58210ba9548Sratchov /* convert u32 to uN */ 58310ba9548Sratchov s >>= oshift; 58410ba9548Sratchov /* convert uN to sN */ 58510ba9548Sratchov s -= obias; 58610ba9548Sratchov /* packetize sN */ 58710ba9548Sratchov for (i = obps; i > 0; i--) { 58810ba9548Sratchov *odata = (unsigned char)s; 58910ba9548Sratchov s >>= 8; 59010ba9548Sratchov odata += obnext; 59110ba9548Sratchov } 59210ba9548Sratchov odata += osnext; 59310ba9548Sratchov } 59410ba9548Sratchov } 59510ba9548Sratchov 59610ba9548Sratchov /* 59710ba9548Sratchov * store "todo" frames of silence in foreign encoding 59810ba9548Sratchov */ 59910ba9548Sratchov void 60010ba9548Sratchov enc_sil_do(struct conv *p, unsigned char *out, int todo) 60110ba9548Sratchov { 60210ba9548Sratchov unsigned int f; 60310ba9548Sratchov unsigned int s; 60410ba9548Sratchov unsigned int oshift; 60510ba9548Sratchov int obias; 60610ba9548Sratchov unsigned int obps; 60710ba9548Sratchov unsigned int i; 60810ba9548Sratchov unsigned char *odata; 60910ba9548Sratchov int obnext; 61010ba9548Sratchov int osnext; 61110ba9548Sratchov 61210ba9548Sratchov #ifdef DEBUG 613*b4d5e3c9Sratchov logx(4, "enc: silence %u frames", todo); 61410ba9548Sratchov #endif 61510ba9548Sratchov /* 61610ba9548Sratchov * Partially copy structures into local variables, to avoid 61710ba9548Sratchov * unnecessary indirections; this also allows the compiler to 61810ba9548Sratchov * order local variables more "cache-friendly". 61910ba9548Sratchov */ 62010ba9548Sratchov odata = out; 62110ba9548Sratchov oshift = p->shift; 62210ba9548Sratchov obias = p->bias; 62310ba9548Sratchov obps = p->bps; 62410ba9548Sratchov obnext = p->bnext; 62510ba9548Sratchov osnext = p->snext; 62610ba9548Sratchov 62710ba9548Sratchov /* 62810ba9548Sratchov * Start conversion. 62910ba9548Sratchov */ 63010ba9548Sratchov odata += p->bfirst; 63110ba9548Sratchov for (f = todo * p->nch; f > 0; f--) { 63210ba9548Sratchov s = ((1U << 31) >> oshift) - obias; 63310ba9548Sratchov for (i = obps; i > 0; i--) { 63410ba9548Sratchov *odata = (unsigned char)s; 63510ba9548Sratchov s >>= 8; 63610ba9548Sratchov odata += obnext; 63710ba9548Sratchov } 63810ba9548Sratchov odata += osnext; 63910ba9548Sratchov } 64010ba9548Sratchov } 64110ba9548Sratchov 64210ba9548Sratchov /* 64310ba9548Sratchov * initialize encoder from native to foreign encoding 64410ba9548Sratchov */ 64510ba9548Sratchov void 64610ba9548Sratchov enc_init(struct conv *p, struct aparams *par, int nch) 64710ba9548Sratchov { 648*b4d5e3c9Sratchov #ifdef DEBUG 649*b4d5e3c9Sratchov char enc_str[ENCMAX]; 650*b4d5e3c9Sratchov #endif 651*b4d5e3c9Sratchov 65210ba9548Sratchov p->nch = nch; 65310ba9548Sratchov p->bps = par->bps; 65410ba9548Sratchov if (par->msb) { 65510ba9548Sratchov p->shift = 32 - par->bps * 8; 65610ba9548Sratchov } else { 65710ba9548Sratchov p->shift = 32 - par->bits; 65810ba9548Sratchov } 65910ba9548Sratchov if (par->sig) { 66010ba9548Sratchov p->bias = (1U << 31) >> p->shift; 66110ba9548Sratchov } else { 66210ba9548Sratchov p->bias = 0; 66310ba9548Sratchov } 66410ba9548Sratchov if (!par->le) { 66510ba9548Sratchov p->bfirst = par->bps - 1; 66610ba9548Sratchov p->bnext = -1; 66710ba9548Sratchov p->snext = 2 * par->bps; 66810ba9548Sratchov } else { 66910ba9548Sratchov p->bfirst = 0; 67010ba9548Sratchov p->bnext = 1; 67110ba9548Sratchov p->snext = 0; 67210ba9548Sratchov } 67310ba9548Sratchov #ifdef DEBUG 674*b4d5e3c9Sratchov logx(3, "enc: %s, %d channels", 675*b4d5e3c9Sratchov (aparams_enctostr(par, enc_str), enc_str), p->nch); 67610ba9548Sratchov #endif 67710ba9548Sratchov } 67810ba9548Sratchov 67910ba9548Sratchov /* 680bbe3c388Sratchov * decode "todo" frames from foreign to native encoding 68110ba9548Sratchov */ 68210ba9548Sratchov void 68310ba9548Sratchov dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) 68410ba9548Sratchov { 68510ba9548Sratchov unsigned int f; 68610ba9548Sratchov unsigned int ibps; 68710ba9548Sratchov unsigned int i; 68810ba9548Sratchov unsigned int s = 0xdeadbeef; 68910ba9548Sratchov unsigned char *idata; 69010ba9548Sratchov int ibnext; 69110ba9548Sratchov int isnext; 69210ba9548Sratchov unsigned int ibias; 69310ba9548Sratchov unsigned int ishift; 69410ba9548Sratchov adata_t *odata; 69510ba9548Sratchov 69610ba9548Sratchov #ifdef DEBUG 697*b4d5e3c9Sratchov logx(4, "dec: copying %u frames", todo); 69810ba9548Sratchov #endif 69910ba9548Sratchov /* 70010ba9548Sratchov * Partially copy structures into local variables, to avoid 70110ba9548Sratchov * unnecessary indirections; this also allows the compiler to 70210ba9548Sratchov * order local variables more "cache-friendly". 70310ba9548Sratchov */ 70410ba9548Sratchov idata = in; 70510ba9548Sratchov odata = (adata_t *)out; 70610ba9548Sratchov ibps = p->bps; 70710ba9548Sratchov ibnext = p->bnext; 70810ba9548Sratchov ibias = p->bias; 70910ba9548Sratchov ishift = p->shift; 71010ba9548Sratchov isnext = p->snext; 71110ba9548Sratchov 71210ba9548Sratchov /* 71310ba9548Sratchov * Start conversion. 71410ba9548Sratchov */ 71510ba9548Sratchov idata += p->bfirst; 71610ba9548Sratchov for (f = todo * p->nch; f > 0; f--) { 71710ba9548Sratchov for (i = ibps; i > 0; i--) { 71810ba9548Sratchov s <<= 8; 71910ba9548Sratchov s |= *idata; 72010ba9548Sratchov idata += ibnext; 72110ba9548Sratchov } 72210ba9548Sratchov idata += isnext; 72310ba9548Sratchov s += ibias; 72410ba9548Sratchov s <<= ishift; 72510ba9548Sratchov s >>= 32 - ADATA_BITS; 72610ba9548Sratchov *odata++ = s - ADATA_UNIT; 72710ba9548Sratchov } 72810ba9548Sratchov } 72910ba9548Sratchov 73010ba9548Sratchov /* 73110ba9548Sratchov * convert a 32-bit float to adata_t, clipping to -1:1, boundaries 73210ba9548Sratchov * excluded 73310ba9548Sratchov */ 73410ba9548Sratchov static inline int 73510ba9548Sratchov f32_to_adata(unsigned int x) 73610ba9548Sratchov { 73710ba9548Sratchov unsigned int s, e, m, y; 73810ba9548Sratchov 73910ba9548Sratchov s = (x >> 31); 74010ba9548Sratchov e = (x >> 23) & 0xff; 74110ba9548Sratchov m = (x << 8) | 0x80000000; 7423e5c3d5eSratchov 7433e5c3d5eSratchov /* 7443e5c3d5eSratchov * f32 exponent is (e - 127) and the point is after the 31-th 7453e5c3d5eSratchov * bit, thus the shift is: 7463e5c3d5eSratchov * 7473e5c3d5eSratchov * 31 - (BITS - 1) - (e - 127) 7483e5c3d5eSratchov * 7493e5c3d5eSratchov * to ensure output is in the 0..(2^BITS)-1 range, the minimum 75022359d65Sratchov * shift is 31 - (BITS - 1) + 1, and maximum shift is 31 7513e5c3d5eSratchov */ 7523e5c3d5eSratchov if (e < 127 - (ADATA_BITS - 1)) 75310ba9548Sratchov y = 0; 75422359d65Sratchov else if (e >= 127) 75510ba9548Sratchov y = ADATA_UNIT - 1; 75610ba9548Sratchov else 75710ba9548Sratchov y = m >> (127 + (32 - ADATA_BITS) - e); 75810ba9548Sratchov return (y ^ -s) + s; 75910ba9548Sratchov } 76010ba9548Sratchov 76110ba9548Sratchov /* 76210ba9548Sratchov * convert samples from little endian ieee 754 floats to adata_t 76310ba9548Sratchov */ 76410ba9548Sratchov void 76510ba9548Sratchov dec_do_float(struct conv *p, unsigned char *in, unsigned char *out, int todo) 76610ba9548Sratchov { 76710ba9548Sratchov unsigned int f; 76810ba9548Sratchov unsigned int i; 76910ba9548Sratchov unsigned int s = 0xdeadbeef; 77010ba9548Sratchov unsigned char *idata; 77110ba9548Sratchov int ibnext; 77210ba9548Sratchov int isnext; 77310ba9548Sratchov adata_t *odata; 77410ba9548Sratchov 77510ba9548Sratchov #ifdef DEBUG 776*b4d5e3c9Sratchov logx(4, "dec_float: copying %u frames", todo); 77710ba9548Sratchov #endif 77810ba9548Sratchov /* 77910ba9548Sratchov * Partially copy structures into local variables, to avoid 78010ba9548Sratchov * unnecessary indirections; this also allows the compiler to 78110ba9548Sratchov * order local variables more "cache-friendly". 78210ba9548Sratchov */ 78310ba9548Sratchov idata = in; 78410ba9548Sratchov odata = (adata_t *)out; 78510ba9548Sratchov ibnext = p->bnext; 78610ba9548Sratchov isnext = p->snext; 78710ba9548Sratchov 78810ba9548Sratchov /* 78910ba9548Sratchov * Start conversion. 79010ba9548Sratchov */ 79110ba9548Sratchov idata += p->bfirst; 79210ba9548Sratchov for (f = todo * p->nch; f > 0; f--) { 79310ba9548Sratchov for (i = 4; i > 0; i--) { 79410ba9548Sratchov s <<= 8; 79510ba9548Sratchov s |= *idata; 79610ba9548Sratchov idata += ibnext; 79710ba9548Sratchov } 79810ba9548Sratchov idata += isnext; 79910ba9548Sratchov *odata++ = f32_to_adata(s); 80010ba9548Sratchov } 80110ba9548Sratchov } 80210ba9548Sratchov 80310ba9548Sratchov /* 80410ba9548Sratchov * convert samples from ulaw/alaw to adata_t 80510ba9548Sratchov */ 80610ba9548Sratchov void 8073d938fd4Sratchov dec_do_ulaw(struct conv *p, unsigned char *in, 8083d938fd4Sratchov unsigned char *out, int todo, int is_alaw) 80910ba9548Sratchov { 81010ba9548Sratchov unsigned int f; 81110ba9548Sratchov unsigned char *idata; 81210ba9548Sratchov adata_t *odata; 813b020cfe1Snaddy const short *map; 81410ba9548Sratchov 81510ba9548Sratchov #ifdef DEBUG 816*b4d5e3c9Sratchov logx(4, "dec_ulaw: copying %u frames", todo); 81710ba9548Sratchov #endif 81810ba9548Sratchov map = is_alaw ? dec_alawmap : dec_ulawmap; 81910ba9548Sratchov idata = in; 82010ba9548Sratchov odata = (adata_t *)out; 82110ba9548Sratchov for (f = todo * p->nch; f > 0; f--) 82210ba9548Sratchov *odata++ = map[*idata++] << (ADATA_BITS - 16); 82310ba9548Sratchov } 82410ba9548Sratchov 82510ba9548Sratchov /* 82610ba9548Sratchov * initialize decoder from foreign to native encoding 82710ba9548Sratchov */ 82810ba9548Sratchov void 82910ba9548Sratchov dec_init(struct conv *p, struct aparams *par, int nch) 83010ba9548Sratchov { 831*b4d5e3c9Sratchov #ifdef DEBUG 832*b4d5e3c9Sratchov char enc_str[ENCMAX]; 833*b4d5e3c9Sratchov #endif 834*b4d5e3c9Sratchov 83510ba9548Sratchov p->bps = par->bps; 83610ba9548Sratchov p->nch = nch; 83710ba9548Sratchov if (par->msb) { 83810ba9548Sratchov p->shift = 32 - par->bps * 8; 83910ba9548Sratchov } else { 84010ba9548Sratchov p->shift = 32 - par->bits; 84110ba9548Sratchov } 84210ba9548Sratchov if (par->sig) { 84310ba9548Sratchov p->bias = (1U << 31) >> p->shift; 84410ba9548Sratchov } else { 84510ba9548Sratchov p->bias = 0; 84610ba9548Sratchov } 84710ba9548Sratchov if (par->le) { 84810ba9548Sratchov p->bfirst = par->bps - 1; 84910ba9548Sratchov p->bnext = -1; 85010ba9548Sratchov p->snext = 2 * par->bps; 85110ba9548Sratchov } else { 85210ba9548Sratchov p->bfirst = 0; 85310ba9548Sratchov p->bnext = 1; 85410ba9548Sratchov p->snext = 0; 85510ba9548Sratchov } 85610ba9548Sratchov #ifdef DEBUG 857*b4d5e3c9Sratchov logx(3, "dec: %s, %d channels", 858*b4d5e3c9Sratchov (aparams_enctostr(par, enc_str), enc_str), p->nch); 85910ba9548Sratchov #endif 86010ba9548Sratchov } 86110ba9548Sratchov 86210ba9548Sratchov /* 86310ba9548Sratchov * mix "todo" input frames on the output with the given volume 86410ba9548Sratchov */ 86510ba9548Sratchov void 86610ba9548Sratchov cmap_add(struct cmap *p, void *in, void *out, int vol, int todo) 86710ba9548Sratchov { 86810ba9548Sratchov adata_t *idata, *odata; 86910ba9548Sratchov int i, j, nch, istart, inext, onext, ostart, y, v; 87010ba9548Sratchov 87110ba9548Sratchov #ifdef DEBUG 872*b4d5e3c9Sratchov logx(4, "cmap: adding %d frames", todo); 87310ba9548Sratchov #endif 87410ba9548Sratchov idata = in; 87510ba9548Sratchov odata = out; 87610ba9548Sratchov ostart = p->ostart; 87710ba9548Sratchov onext = p->onext; 87810ba9548Sratchov istart = p->istart; 87910ba9548Sratchov inext = p->inext; 88010ba9548Sratchov nch = p->nch; 88110ba9548Sratchov v = vol; 88210ba9548Sratchov 88310ba9548Sratchov /* 88410ba9548Sratchov * map/mix input on the output 88510ba9548Sratchov */ 88610ba9548Sratchov for (i = todo; i > 0; i--) { 88710ba9548Sratchov odata += ostart; 88810ba9548Sratchov idata += istart; 88910ba9548Sratchov for (j = nch; j > 0; j--) { 89010ba9548Sratchov y = *odata + ADATA_MUL(*idata, v); 89110ba9548Sratchov if (y >= ADATA_UNIT) 89210ba9548Sratchov y = ADATA_UNIT - 1; 89310ba9548Sratchov else if (y < -ADATA_UNIT) 89410ba9548Sratchov y = -ADATA_UNIT; 89510ba9548Sratchov *odata = y; 89610ba9548Sratchov idata++; 89710ba9548Sratchov odata++; 89810ba9548Sratchov } 89910ba9548Sratchov odata += onext; 90010ba9548Sratchov idata += inext; 90110ba9548Sratchov } 90210ba9548Sratchov } 90310ba9548Sratchov 90410ba9548Sratchov /* 905bbe3c388Sratchov * overwrite output with "todo" input frames with the given volume 90610ba9548Sratchov */ 90710ba9548Sratchov void 90810ba9548Sratchov cmap_copy(struct cmap *p, void *in, void *out, int vol, int todo) 90910ba9548Sratchov { 91010ba9548Sratchov adata_t *idata, *odata; 91110ba9548Sratchov int i, j, nch, istart, inext, onext, ostart, v; 91210ba9548Sratchov 91310ba9548Sratchov #ifdef DEBUG 914*b4d5e3c9Sratchov logx(4, "cmap: copying %d frames", todo); 91510ba9548Sratchov #endif 91610ba9548Sratchov idata = in; 91710ba9548Sratchov odata = out; 91810ba9548Sratchov ostart = p->ostart; 91910ba9548Sratchov onext = p->onext; 92010ba9548Sratchov istart = p->istart; 92110ba9548Sratchov inext = p->inext; 92210ba9548Sratchov nch = p->nch; 92310ba9548Sratchov v = vol; 92410ba9548Sratchov 92510ba9548Sratchov /* 92610ba9548Sratchov * copy to the output buffer 92710ba9548Sratchov */ 92810ba9548Sratchov for (i = todo; i > 0; i--) { 92910ba9548Sratchov idata += istart; 93010ba9548Sratchov odata += ostart; 93110ba9548Sratchov for (j = nch; j > 0; j--) { 93210ba9548Sratchov *odata = ADATA_MUL(*idata, v); 93310ba9548Sratchov odata++; 93410ba9548Sratchov idata++; 93510ba9548Sratchov } 93610ba9548Sratchov odata += onext; 93710ba9548Sratchov idata += inext; 93810ba9548Sratchov } 93910ba9548Sratchov } 94010ba9548Sratchov 94110ba9548Sratchov /* 94210ba9548Sratchov * initialize channel mapper, to map a subset of input channel range 94310ba9548Sratchov * into a subset of the output channel range 94410ba9548Sratchov */ 94510ba9548Sratchov void 94610ba9548Sratchov cmap_init(struct cmap *p, 94710ba9548Sratchov int imin, int imax, int isubmin, int isubmax, 94810ba9548Sratchov int omin, int omax, int osubmin, int osubmax) 94910ba9548Sratchov { 950e670b539Sratchov int inch, onch, nch; 95110ba9548Sratchov 952e670b539Sratchov /* 953e670b539Sratchov * Ignore channels outside of the available sets 954e670b539Sratchov */ 955e670b539Sratchov if (isubmin < imin) 956e670b539Sratchov isubmin = imin; 957e670b539Sratchov if (isubmax > imax) 958e670b539Sratchov isubmax = imax; 959e670b539Sratchov if (osubmin < omin) 960e670b539Sratchov osubmin = omin; 961e670b539Sratchov if (osubmax > omax) 962e670b539Sratchov osubmax = omax; 96310ba9548Sratchov 964e670b539Sratchov /* 965e670b539Sratchov * Shrink the input or the output subset to make both subsets of 966e670b539Sratchov * the same size 967e670b539Sratchov */ 968e670b539Sratchov inch = isubmax - isubmin + 1; 969e670b539Sratchov onch = osubmax - osubmin + 1; 970e670b539Sratchov nch = (inch < onch) ? inch : onch; 971e670b539Sratchov isubmax = isubmin + nch - 1; 972e670b539Sratchov osubmax = osubmin + nch - 1; 97310ba9548Sratchov 974e670b539Sratchov p->ostart = osubmin - omin; 975e670b539Sratchov p->onext = omax - osubmax; 976e670b539Sratchov p->istart = isubmin - imin; 977e670b539Sratchov p->inext = imax - isubmax; 978e670b539Sratchov p->nch = nch; 97910ba9548Sratchov #ifdef DEBUG 980*b4d5e3c9Sratchov logx(3, "%s: nch = %d, ostart = %d, onext = %d, istart = %d, inext = %d", 981*b4d5e3c9Sratchov __func__, p->nch, p->ostart, p->onext, p->istart, p->inext); 98210ba9548Sratchov #endif 98310ba9548Sratchov } 984