xref: /freebsd/sys/dev/sound/pcm/pcm.h (revision c824383b269d8abe175ea4751194660716d5600e)
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