1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2006-2009 Ariff Abdullah <ariff@FreeBSD.org>
5 * All rights reserved.
6 * Copyright (c) 2024-2025 The FreeBSD Foundation
7 *
8 * Portions of this software were developed by Christos Margiolis
9 * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #ifndef _SND_PCM_H_
34 #define _SND_PCM_H_
35
36 #include <sys/param.h>
37
38 #include <dev/sound/pcm/g711.h>
39
40 #ifndef _KERNEL
41 #include <assert.h> /* for __assert_unreachable() */
42 #endif
43
44 /*
45 * Automatically turn on 64bit arithmetic on suitable archs
46 * (amd64 64bit, etc..) for wider 32bit samples / integer processing.
47 */
48 #if LONG_BIT >= 64
49 #undef SND_PCM_64
50 #define SND_PCM_64 1
51 #endif
52
53 typedef int32_t intpcm_t;
54
55 typedef int32_t intpcm8_t;
56 typedef int32_t intpcm16_t;
57 typedef int32_t intpcm24_t;
58
59 typedef uint32_t uintpcm_t;
60
61 typedef uint32_t uintpcm8_t;
62 typedef uint32_t uintpcm16_t;
63 typedef uint32_t uintpcm24_t;
64
65 #ifdef SND_PCM_64
66 typedef int64_t intpcm32_t;
67 typedef uint64_t uintpcm32_t;
68 #else
69 typedef int32_t intpcm32_t;
70 typedef uint32_t uintpcm32_t;
71 #endif
72
73 typedef int64_t intpcm64_t;
74 typedef uint64_t uintpcm64_t;
75
76 /* 32bit fixed point shift */
77 #define PCM_FXSHIFT 8
78
79 #define PCM_S8_MAX 0x7f
80 #define PCM_S8_MIN -0x80
81 #define PCM_S16_MAX 0x7fff
82 #define PCM_S16_MIN -0x8000
83 #define PCM_S24_MAX 0x7fffff
84 #define PCM_S24_MIN -0x800000
85 #ifdef SND_PCM_64
86 #if LONG_BIT >= 64
87 #define PCM_S32_MAX 0x7fffffffL
88 #define PCM_S32_MIN -0x80000000L
89 #else
90 #define PCM_S32_MAX 0x7fffffffLL
91 #define PCM_S32_MIN -0x80000000LL
92 #endif
93 #else
94 #define PCM_S32_MAX 0x7fffffff
95 #define PCM_S32_MIN (-0x7fffffff - 1)
96 #endif
97
98 /* Bytes-per-sample definition */
99 #define PCM_8_BPS 1
100 #define PCM_16_BPS 2
101 #define PCM_24_BPS 3
102 #define PCM_32_BPS 4
103
104 #define INTPCM_T(v) ((intpcm_t)(v))
105 #define INTPCM8_T(v) ((intpcm8_t)(v))
106 #define INTPCM16_T(v) ((intpcm16_t)(v))
107 #define INTPCM24_T(v) ((intpcm24_t)(v))
108 #define INTPCM32_T(v) ((intpcm32_t)(v))
109
110 static const struct {
111 const uint8_t ulaw_to_u8[G711_TABLE_SIZE];
112 const uint8_t alaw_to_u8[G711_TABLE_SIZE];
113 const uint8_t u8_to_ulaw[G711_TABLE_SIZE];
114 const uint8_t u8_to_alaw[G711_TABLE_SIZE];
115 } xlaw_conv_tables = {
116 ULAW_TO_U8,
117 ALAW_TO_U8,
118 U8_TO_ULAW,
119 U8_TO_ALAW
120 };
121
122 /*
123 * Functions for reading/writing PCM integer sample values from bytes array.
124 * Since every process is done using signed integer (and to make our life less
125 * miserable), unsigned sample will be converted to its signed counterpart and
126 * restored during writing back.
127 */
128 static __always_inline __unused intpcm_t
pcm_sample_read(const uint8_t * src,uint32_t fmt)129 pcm_sample_read(const uint8_t *src, uint32_t fmt)
130 {
131 intpcm_t v, e, m;
132 bool s;
133
134 fmt = AFMT_ENCODING(fmt);
135
136 switch (fmt) {
137 case AFMT_AC3:
138 v = 0;
139 break;
140 case AFMT_MU_LAW:
141 v = _G711_TO_INTPCM(xlaw_conv_tables.ulaw_to_u8, *src);
142 break;
143 case AFMT_A_LAW:
144 v = _G711_TO_INTPCM(xlaw_conv_tables.alaw_to_u8, *src);
145 break;
146 case AFMT_S8:
147 v = INTPCM_T((int8_t)*src);
148 break;
149 case AFMT_U8:
150 v = INTPCM_T((int8_t)(*src ^ 0x80));
151 break;
152 case AFMT_S16_LE:
153 v = INTPCM_T(src[0] | (int8_t)src[1] << 8);
154 break;
155 case AFMT_S16_BE:
156 v = INTPCM_T(src[1] | (int8_t)src[0] << 8);
157 break;
158 case AFMT_U16_LE:
159 v = INTPCM_T(src[0] | (int8_t)(src[1] ^ 0x80) << 8);
160 break;
161 case AFMT_U16_BE:
162 v = INTPCM_T(src[1] | (int8_t)(src[0] ^ 0x80) << 8);
163 break;
164 case AFMT_S24_LE:
165 v = INTPCM_T(src[0] | src[1] << 8 | (int8_t)src[2] << 16);
166 break;
167 case AFMT_S24_BE:
168 v = INTPCM_T(src[2] | src[1] << 8 | (int8_t)src[0] << 16);
169 break;
170 case AFMT_U24_LE:
171 v = INTPCM_T(src[0] | src[1] << 8 |
172 (int8_t)(src[2] ^ 0x80) << 16);
173 break;
174 case AFMT_U24_BE:
175 v = INTPCM_T(src[2] | src[1] << 8 |
176 (int8_t)(src[0] ^ 0x80) << 16);
177 break;
178 case AFMT_S32_LE:
179 v = INTPCM_T(src[0] | src[1] << 8 | src[2] << 16 |
180 (int8_t)src[3] << 24);
181 break;
182 case AFMT_S32_BE:
183 v = INTPCM_T(src[3] | src[2] << 8 | src[1] << 16 |
184 (int8_t)src[0] << 24);
185 break;
186 case AFMT_U32_LE:
187 v = INTPCM_T(src[0] | src[1] << 8 | src[2] << 16 |
188 (int8_t)(src[3] ^ 0x80) << 24);
189 break;
190 case AFMT_U32_BE:
191 v = INTPCM_T(src[3] | src[2] << 8 | src[1] << 16 |
192 (int8_t)(src[0] ^ 0x80) << 24);
193 break;
194 case AFMT_F32_LE: /* FALLTHROUGH */
195 case AFMT_F32_BE:
196 if (fmt == AFMT_F32_LE) {
197 v = INTPCM_T(src[0] | src[1] << 8 | src[2] << 16 |
198 (int8_t)src[3] << 24);
199 } else {
200 v = INTPCM_T(src[3] | src[2] << 8 | src[1] << 16 |
201 (int8_t)src[0] << 24);
202 }
203 e = (v >> 23) & 0xff;
204 /* NaN, +/- Inf or too small */
205 if (e == 0xff || e < 96) {
206 v = INTPCM_T(0);
207 break;
208 }
209 s = v & 0x80000000U;
210 if (e > 126) {
211 v = INTPCM_T((s == 0) ? PCM_S32_MAX : PCM_S32_MIN);
212 break;
213 }
214 m = 0x800000 | (v & 0x7fffff);
215 e += 8 - 127;
216 if (e < 0)
217 m >>= -e;
218 else
219 m <<= e;
220 v = INTPCM_T((s == 0) ? m : -m);
221 break;
222 default:
223 v = 0;
224 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
225 __assert_unreachable();
226 }
227
228 return (v);
229 }
230
231 /*
232 * Read sample and normalize to 32-bit magnitude.
233 */
234 static __always_inline __unused intpcm_t
pcm_sample_read_norm(const uint8_t * src,uint32_t fmt)235 pcm_sample_read_norm(const uint8_t *src, uint32_t fmt)
236 {
237 return (pcm_sample_read(src, fmt) << (32 - AFMT_BIT(fmt)));
238 }
239
240 /*
241 * Read sample and restrict magnitude to 24 bits.
242 */
243 static __always_inline __unused intpcm_t
pcm_sample_read_calc(const uint8_t * src,uint32_t fmt)244 pcm_sample_read_calc(const uint8_t *src, uint32_t fmt)
245 {
246 intpcm_t v;
247
248 v = pcm_sample_read(src, fmt);
249
250 #ifndef SND_PCM_64
251 /*
252 * Dynamic range for humans: ~140db.
253 *
254 * 16bit = 96db (close enough)
255 * 24bit = 144db (perfect)
256 * 32bit = 196db (way too much)
257 *
258 * 24bit is pretty much sufficient for our signed integer processing.
259 * Also, to avoid overflow, we truncate 32bit (and only 32bit) samples
260 * down to 24bit (see below for the reason), unless SND_PCM_64 is
261 * defined.
262 */
263 if (fmt & AFMT_32BIT)
264 v >>= PCM_FXSHIFT;
265 #endif
266
267 return (v);
268 }
269
270 static __always_inline __unused void
pcm_sample_write(uint8_t * dst,intpcm_t v,uint32_t fmt)271 pcm_sample_write(uint8_t *dst, intpcm_t v, uint32_t fmt)
272 {
273 intpcm_t r, e;
274
275 fmt = AFMT_ENCODING(fmt);
276
277 if (fmt & (AFMT_F32_LE | AFMT_F32_BE)) {
278 if (v == 0)
279 r = 0;
280 else if (v == PCM_S32_MAX)
281 r = 0x3f800000;
282 else if (v == PCM_S32_MIN)
283 r = 0x80000000U | 0x3f800000;
284 else {
285 r = 0;
286 if (v < 0) {
287 r |= 0x80000000U;
288 v = -v;
289 }
290 e = 127 - 8;
291 while ((v & 0x7f000000) != 0) {
292 v >>= 1;
293 e++;
294 }
295 while ((v & 0x7f800000) == 0) {
296 v <<= 1;
297 e--;
298 }
299 r |= (e & 0xff) << 23;
300 r |= v & 0x7fffff;
301 }
302 v = r;
303 }
304
305 switch (fmt) {
306 case AFMT_AC3:
307 *(int16_t *)dst = 0;
308 break;
309 case AFMT_MU_LAW:
310 *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_ulaw, v);
311 break;
312 case AFMT_A_LAW:
313 *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_alaw, v);
314 break;
315 case AFMT_S8:
316 *(int8_t *)dst = v;
317 break;
318 case AFMT_U8:
319 *(int8_t *)dst = v ^ 0x80;
320 break;
321 case AFMT_S16_LE:
322 dst[0] = v;
323 dst[1] = v >> 8;
324 break;
325 case AFMT_S16_BE:
326 dst[1] = v;
327 dst[0] = v >> 8;
328 break;
329 case AFMT_U16_LE:
330 dst[0] = v;
331 dst[1] = (v >> 8) ^ 0x80;
332 break;
333 case AFMT_U16_BE:
334 dst[1] = v;
335 dst[0] = (v >> 8) ^ 0x80;
336 break;
337 case AFMT_S24_LE:
338 dst[0] = v;
339 dst[1] = v >> 8;
340 dst[2] = v >> 16;
341 break;
342 case AFMT_S24_BE:
343 dst[2] = v;
344 dst[1] = v >> 8;
345 dst[0] = v >> 16;
346 break;
347 case AFMT_U24_LE:
348 dst[0] = v;
349 dst[1] = v >> 8;
350 dst[2] = (v >> 16) ^ 0x80;
351 break;
352 case AFMT_U24_BE:
353 dst[2] = v;
354 dst[1] = v >> 8;
355 dst[0] = (v >> 16) ^ 0x80;
356 break;
357 case AFMT_S32_LE: /* FALLTHROUGH */
358 case AFMT_F32_LE:
359 dst[0] = v;
360 dst[1] = v >> 8;
361 dst[2] = v >> 16;
362 dst[3] = v >> 24;
363 break;
364 case AFMT_S32_BE: /* FALLTHROUGH */
365 case AFMT_F32_BE:
366 dst[3] = v;
367 dst[2] = v >> 8;
368 dst[1] = v >> 16;
369 dst[0] = v >> 24;
370 break;
371 case AFMT_U32_LE:
372 dst[0] = v;
373 dst[1] = v >> 8;
374 dst[2] = v >> 16;
375 dst[3] = (v >> 24) ^ 0x80;
376 break;
377 case AFMT_U32_BE:
378 dst[3] = v;
379 dst[2] = v >> 8;
380 dst[1] = v >> 16;
381 dst[0] = (v >> 24) ^ 0x80;
382 break;
383 default:
384 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
385 __assert_unreachable();
386 }
387 }
388
389 /*
390 * Write sample and normalize to original magnitude.
391 */
392 static __always_inline __unused void
pcm_sample_write_norm(uint8_t * dst,intpcm_t v,uint32_t fmt)393 pcm_sample_write_norm(uint8_t *dst, intpcm_t v, uint32_t fmt)
394 {
395 pcm_sample_write(dst, v >> (32 - AFMT_BIT(fmt)), fmt);
396 }
397
398 /*
399 * To be used with pcm_sample_read_calc().
400 */
401 static __always_inline __unused void
pcm_sample_write_calc(uint8_t * dst,intpcm_t v,uint32_t fmt)402 pcm_sample_write_calc(uint8_t *dst, intpcm_t v, uint32_t fmt)
403 {
404 #ifndef SND_PCM_64
405 /* Shift back to 32-bit magnitude. */
406 if (fmt & AFMT_32BIT)
407 v <<= PCM_FXSHIFT;
408 #endif
409 pcm_sample_write(dst, v, fmt);
410 }
411
412 static __always_inline __unused intpcm_t
pcm_clamp(intpcm32_t sample,uint32_t fmt)413 pcm_clamp(intpcm32_t sample, uint32_t fmt)
414 {
415 fmt = AFMT_ENCODING(fmt);
416
417 switch (AFMT_BIT(fmt)) {
418 case 8:
419 return ((sample > PCM_S8_MAX) ? PCM_S8_MAX :
420 ((sample < PCM_S8_MIN) ? PCM_S8_MIN : sample));
421 case 16:
422 return ((sample > PCM_S16_MAX) ? PCM_S16_MAX :
423 ((sample < PCM_S16_MIN) ? PCM_S16_MIN : sample));
424 case 24:
425 return ((sample > PCM_S24_MAX) ? PCM_S24_MAX :
426 ((sample < PCM_S24_MIN) ? PCM_S24_MIN : sample));
427 case 32:
428 return ((sample > PCM_S32_MAX) ? PCM_S32_MAX :
429 ((sample < PCM_S32_MIN) ? PCM_S32_MIN : sample));
430 default:
431 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
432 __assert_unreachable();
433 }
434 }
435
436 static __always_inline __unused intpcm_t
pcm_clamp_calc(intpcm32_t sample,uint32_t fmt)437 pcm_clamp_calc(intpcm32_t sample, uint32_t fmt)
438 {
439 #ifndef SND_PCM_64
440 if (fmt & AFMT_32BIT) {
441 return ((sample > PCM_S24_MAX) ? PCM_S32_MAX :
442 ((sample < PCM_S24_MIN) ? PCM_S32_MIN :
443 sample << PCM_FXSHIFT));
444 }
445 #endif
446
447 return (pcm_clamp(sample, fmt));
448 }
449
450 #endif /* !_SND_PCM_H_ */
451