xref: /openbsd-src/usr.bin/aucat/dsp.c (revision b4d5e3c92baf7ae1b3dcb69a4c795856a3c74115)
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