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;
132
133 fmt = AFMT_ENCODING(fmt);
134
135 switch (fmt) {
136 case AFMT_AC3:
137 v = 0;
138 break;
139 case AFMT_MU_LAW:
140 v = _G711_TO_INTPCM(xlaw_conv_tables.ulaw_to_u8, *src);
141 break;
142 case AFMT_A_LAW:
143 v = _G711_TO_INTPCM(xlaw_conv_tables.alaw_to_u8, *src);
144 break;
145 case AFMT_S8:
146 v = INTPCM_T((int8_t)*src);
147 break;
148 case AFMT_U8:
149 v = INTPCM_T((int8_t)(*src ^ 0x80));
150 break;
151 case AFMT_S16_LE:
152 v = INTPCM_T(src[0] | (int8_t)src[1] << 8);
153 break;
154 case AFMT_S16_BE:
155 v = INTPCM_T(src[1] | (int8_t)src[0] << 8);
156 break;
157 case AFMT_U16_LE:
158 v = INTPCM_T(src[0] | (int8_t)(src[1] ^ 0x80) << 8);
159 break;
160 case AFMT_U16_BE:
161 v = INTPCM_T(src[1] | (int8_t)(src[0] ^ 0x80) << 8);
162 break;
163 case AFMT_S24_LE:
164 v = INTPCM_T(src[0] | src[1] << 8 | (int8_t)src[2] << 16);
165 break;
166 case AFMT_S24_BE:
167 v = INTPCM_T(src[2] | src[1] << 8 | (int8_t)src[0] << 16);
168 break;
169 case AFMT_U24_LE:
170 v = INTPCM_T(src[0] | src[1] << 8 |
171 (int8_t)(src[2] ^ 0x80) << 16);
172 break;
173 case AFMT_U24_BE:
174 v = INTPCM_T(src[2] | src[1] << 8 |
175 (int8_t)(src[0] ^ 0x80) << 16);
176 break;
177 case AFMT_S32_LE:
178 v = INTPCM_T(src[0] | src[1] << 8 | src[2] << 16 |
179 (int8_t)src[3] << 24);
180 break;
181 case AFMT_S32_BE:
182 v = INTPCM_T(src[3] | src[2] << 8 | src[1] << 16 |
183 (int8_t)src[0] << 24);
184 break;
185 case AFMT_U32_LE:
186 v = INTPCM_T(src[0] | src[1] << 8 | src[2] << 16 |
187 (int8_t)(src[3] ^ 0x80) << 24);
188 break;
189 case AFMT_U32_BE:
190 v = INTPCM_T(src[3] | src[2] << 8 | src[1] << 16 |
191 (int8_t)(src[0] ^ 0x80) << 24);
192 break;
193 default:
194 v = 0;
195 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
196 __assert_unreachable();
197 }
198
199 return (v);
200 }
201
202 /*
203 * Read sample and normalize to 32-bit magnitude.
204 */
205 static __always_inline __unused intpcm_t
pcm_sample_read_norm(const uint8_t * src,uint32_t fmt)206 pcm_sample_read_norm(const uint8_t *src, uint32_t fmt)
207 {
208 return (pcm_sample_read(src, fmt) << (32 - AFMT_BIT(fmt)));
209 }
210
211 /*
212 * Read sample and restrict magnitude to 24 bits.
213 */
214 static __always_inline __unused intpcm_t
pcm_sample_read_calc(const uint8_t * src,uint32_t fmt)215 pcm_sample_read_calc(const uint8_t *src, uint32_t fmt)
216 {
217 intpcm_t v;
218
219 v = pcm_sample_read(src, fmt);
220
221 #ifndef SND_PCM_64
222 /*
223 * Dynamic range for humans: ~140db.
224 *
225 * 16bit = 96db (close enough)
226 * 24bit = 144db (perfect)
227 * 32bit = 196db (way too much)
228 *
229 * 24bit is pretty much sufficient for our signed integer processing.
230 * Also, to avoid overflow, we truncate 32bit (and only 32bit) samples
231 * down to 24bit (see below for the reason), unless SND_PCM_64 is
232 * defined.
233 */
234 if (fmt & AFMT_32BIT)
235 v >>= PCM_FXSHIFT;
236 #endif
237
238 return (v);
239 }
240
241 static __always_inline __unused void
pcm_sample_write(uint8_t * dst,intpcm_t v,uint32_t fmt)242 pcm_sample_write(uint8_t *dst, intpcm_t v, uint32_t fmt)
243 {
244 fmt = AFMT_ENCODING(fmt);
245
246 switch (fmt) {
247 case AFMT_AC3:
248 *(int16_t *)dst = 0;
249 break;
250 case AFMT_MU_LAW:
251 *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_ulaw, v);
252 break;
253 case AFMT_A_LAW:
254 *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_alaw, v);
255 break;
256 case AFMT_S8:
257 *(int8_t *)dst = v;
258 break;
259 case AFMT_U8:
260 *(int8_t *)dst = v ^ 0x80;
261 break;
262 case AFMT_S16_LE:
263 dst[0] = v;
264 dst[1] = v >> 8;
265 break;
266 case AFMT_S16_BE:
267 dst[1] = v;
268 dst[0] = v >> 8;
269 break;
270 case AFMT_U16_LE:
271 dst[0] = v;
272 dst[1] = (v >> 8) ^ 0x80;
273 break;
274 case AFMT_U16_BE:
275 dst[1] = v;
276 dst[0] = (v >> 8) ^ 0x80;
277 break;
278 case AFMT_S24_LE:
279 dst[0] = v;
280 dst[1] = v >> 8;
281 dst[2] = v >> 16;
282 break;
283 case AFMT_S24_BE:
284 dst[2] = v;
285 dst[1] = v >> 8;
286 dst[0] = v >> 16;
287 break;
288 case AFMT_U24_LE:
289 dst[0] = v;
290 dst[1] = v >> 8;
291 dst[2] = (v >> 16) ^ 0x80;
292 break;
293 case AFMT_U24_BE:
294 dst[2] = v;
295 dst[1] = v >> 8;
296 dst[0] = (v >> 16) ^ 0x80;
297 break;
298 case AFMT_S32_LE:
299 dst[0] = v;
300 dst[1] = v >> 8;
301 dst[2] = v >> 16;
302 dst[3] = v >> 24;
303 break;
304 case AFMT_S32_BE:
305 dst[3] = v;
306 dst[2] = v >> 8;
307 dst[1] = v >> 16;
308 dst[0] = v >> 24;
309 break;
310 case AFMT_U32_LE:
311 dst[0] = v;
312 dst[1] = v >> 8;
313 dst[2] = v >> 16;
314 dst[3] = (v >> 24) ^ 0x80;
315 break;
316 case AFMT_U32_BE:
317 dst[3] = v;
318 dst[2] = v >> 8;
319 dst[1] = v >> 16;
320 dst[0] = (v >> 24) ^ 0x80;
321 break;
322 default:
323 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
324 __assert_unreachable();
325 }
326 }
327
328 /*
329 * Write sample and normalize to original magnitude.
330 */
331 static __always_inline __unused void
pcm_sample_write_norm(uint8_t * dst,intpcm_t v,uint32_t fmt)332 pcm_sample_write_norm(uint8_t *dst, intpcm_t v, uint32_t fmt)
333 {
334 pcm_sample_write(dst, v >> (32 - AFMT_BIT(fmt)), fmt);
335 }
336
337 /*
338 * To be used with pcm_sample_read_calc().
339 */
340 static __always_inline __unused void
pcm_sample_write_calc(uint8_t * dst,intpcm_t v,uint32_t fmt)341 pcm_sample_write_calc(uint8_t *dst, intpcm_t v, uint32_t fmt)
342 {
343 #ifndef SND_PCM_64
344 /* Shift back to 32-bit magnitude. */
345 if (fmt & AFMT_32BIT)
346 v <<= PCM_FXSHIFT;
347 #endif
348 pcm_sample_write(dst, v, fmt);
349 }
350
351 static __always_inline __unused intpcm_t
pcm_clamp(intpcm32_t sample,uint32_t fmt)352 pcm_clamp(intpcm32_t sample, uint32_t fmt)
353 {
354 fmt = AFMT_ENCODING(fmt);
355
356 switch (AFMT_BIT(fmt)) {
357 case 8:
358 return ((sample > PCM_S8_MAX) ? PCM_S8_MAX :
359 ((sample < PCM_S8_MIN) ? PCM_S8_MIN : sample));
360 case 16:
361 return ((sample > PCM_S16_MAX) ? PCM_S16_MAX :
362 ((sample < PCM_S16_MIN) ? PCM_S16_MIN : sample));
363 case 24:
364 return ((sample > PCM_S24_MAX) ? PCM_S24_MAX :
365 ((sample < PCM_S24_MIN) ? PCM_S24_MIN : sample));
366 case 32:
367 return ((sample > PCM_S32_MAX) ? PCM_S32_MAX :
368 ((sample < PCM_S32_MIN) ? PCM_S32_MIN : sample));
369 default:
370 printf("%s(): unknown format: 0x%08x\n", __func__, fmt);
371 __assert_unreachable();
372 }
373 }
374
375 static __always_inline __unused intpcm_t
pcm_clamp_calc(intpcm32_t sample,uint32_t fmt)376 pcm_clamp_calc(intpcm32_t sample, uint32_t fmt)
377 {
378 #ifndef SND_PCM_64
379 if (fmt & AFMT_32BIT) {
380 return ((sample > PCM_S24_MAX) ? PCM_S32_MAX :
381 ((sample < PCM_S24_MIN) ? PCM_S32_MIN :
382 sample << PCM_FXSHIFT));
383 }
384 #endif
385
386 return (pcm_clamp(sample, fmt));
387 }
388
389 #endif /* !_SND_PCM_H_ */
390