2 * Copyright (c) 2006-2009 Ariff Abdullah <ariff@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: head/sys/dev/sound/pcm/pcm.h 268351 2014-07-07 00:27:09Z marcel $
32 #include <sys/param.h>
35 * Macros for reading/writing PCM sample / int values from bytes array.
36 * Since every process is done using signed integer (and to make our life
37 * less miserable), unsigned sample will be converted to its signed
38 * counterpart and restored during writing back. To avoid overflow,
39 * we truncate 32bit (and only 32bit) samples down to 24bit (see below
40 * for the reason), unless SND_PCM_64 is defined.
44 * Automatically turn on 64bit arithmetic on suitable archs
45 * (amd64 64bit, etc..) for wider 32bit samples / integer processing.
52 typedef int32_t intpcm_t;
54 typedef int32_t intpcm8_t;
55 typedef int32_t intpcm16_t;
56 typedef int32_t intpcm24_t;
58 typedef uint32_t uintpcm_t;
60 typedef uint32_t uintpcm8_t;
61 typedef uint32_t uintpcm16_t;
62 typedef uint32_t uintpcm24_t;
65 typedef int64_t intpcm32_t;
66 typedef uint64_t uintpcm32_t;
68 typedef int32_t intpcm32_t;
69 typedef uint32_t uintpcm32_t;
72 typedef int64_t intpcm64_t;
73 typedef uint64_t uintpcm64_t;
75 /* 32bit fixed point shift */
78 #define PCM_S8_MAX 0x7f
79 #define PCM_S8_MIN -0x80
80 #define PCM_S16_MAX 0x7fff
81 #define PCM_S16_MIN -0x8000
82 #define PCM_S24_MAX 0x7fffff
83 #define PCM_S24_MIN -0x800000
86 #define PCM_S32_MAX 0x7fffffffL
87 #define PCM_S32_MIN -0x80000000L
89 #define PCM_S32_MAX 0x7fffffffLL
90 #define PCM_S32_MIN -0x80000000LL
93 #define PCM_S32_MAX 0x7fffffff
94 #define PCM_S32_MIN (-0x7fffffff - 1)
97 /* Bytes-per-sample definition */
103 #define INTPCM_T(v) ((intpcm_t)(v))
104 #define INTPCM8_T(v) ((intpcm8_t)(v))
105 #define INTPCM16_T(v) ((intpcm16_t)(v))
106 #define INTPCM24_T(v) ((intpcm24_t)(v))
107 #define INTPCM32_T(v) ((intpcm32_t)(v))
109 #if BYTE_ORDER == LITTLE_ENDIAN
110 #define _PCM_READ_S16_LE(b8) INTPCM_T(*((int16_t *)(b8)))
111 #define _PCM_READ_S32_LE(b8) INTPCM_T(*((int32_t *)(b8)))
112 #define _PCM_READ_S16_BE(b8) \
113 INTPCM_T((b8)[1] | (((int8_t)((b8)[0])) << 8))
114 #define _PCM_READ_S32_BE(b8) \
115 INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) | \
116 (((int8_t)((b8)[0])) << 24))
118 #define _PCM_WRITE_S16_LE(b8, val) do { \
119 *((int16_t *)(b8)) = (val); \
121 #define _PCM_WRITE_S32_LE(b8, val) do { \
122 *((int32_t *)(b8)) = (val); \
124 #define _PCM_WRITE_S16_BE(bb8, vval) do { \
125 intpcm_t val = (vval); \
126 uint8_t *b8 = (bb8); \
130 #define _PCM_WRITE_S32_BE(bb8, vval) do { \
131 intpcm_t val = (vval); \
132 uint8_t *b8 = (bb8); \
139 #define _PCM_READ_U16_LE(b8) \
140 INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
141 #define _PCM_READ_U32_LE(b8) \
142 INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
143 #define _PCM_READ_U16_BE(b8) \
144 INTPCM_T((b8)[1] | (((int8_t)((b8)[0] ^ 0x80)) << 8))
145 #define _PCM_READ_U32_BE(b8) \
146 INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) | \
147 (((int8_t)((b8)[0] ^ 0x80)) << 24))
149 #define _PCM_WRITE_U16_LE(b8, val) do { \
150 *((uint16_t *)(b8)) = (val) ^ 0x8000; \
152 #define _PCM_WRITE_U32_LE(b8, val) do { \
153 *((uint32_t *)(b8)) = (val) ^ 0x80000000; \
155 #define _PCM_WRITE_U16_BE(bb8, vval) do { \
156 intpcm_t val = (vval); \
157 uint8_t *b8 = (bb8); \
159 b8[0] = (val >> 8) ^ 0x80; \
161 #define _PCM_WRITE_U32_BE(bb8, vval) do { \
162 intpcm_t val = (vval); \
163 uint8_t *b8 = (bb8); \
167 b8[0] = (val >> 24) ^ 0x80; \
170 #define _PCM_READ_S16_NE(b8) _PCM_READ_S16_LE(b8)
171 #define _PCM_READ_U16_NE(b8) _PCM_READ_U16_LE(b8)
172 #define _PCM_READ_S32_NE(b8) _PCM_READ_S32_LE(b8)
173 #define _PCM_READ_U32_NE(b8) _PCM_READ_U32_LE(b8)
174 #define _PCM_WRITE_S16_NE(b6) _PCM_WRITE_S16_LE(b8)
175 #define _PCM_WRITE_U16_NE(b6) _PCM_WRITE_U16_LE(b8)
176 #define _PCM_WRITE_S32_NE(b6) _PCM_WRITE_S32_LE(b8)
177 #define _PCM_WRITE_U32_NE(b6) _PCM_WRITE_U32_LE(b8)
178 #else /* !LITTLE_ENDIAN */
179 #define _PCM_READ_S16_LE(b8) \
180 INTPCM_T((b8)[0] | (((int8_t)((b8)[1])) << 8))
181 #define _PCM_READ_S32_LE(b8) \
182 INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) | \
183 (((int8_t)((b8)[3])) << 24))
184 #define _PCM_READ_S16_BE(b8) INTPCM_T(*((int16_t *)(b8)))
185 #define _PCM_READ_S32_BE(b8) INTPCM_T(*((int32_t *)(b8)))
187 #define _PCM_WRITE_S16_LE(bb8, vval) do { \
188 intpcm_t val = (vval); \
189 uint8_t *b8 = (bb8); \
193 #define _PCM_WRITE_S32_LE(bb8, vval) do { \
194 intpcm_t val = (vval); \
195 uint8_t *b8 = (bb8); \
201 #define _PCM_WRITE_S16_BE(b8, val) do { \
202 *((int16_t *)(b8)) = (val); \
204 #define _PCM_WRITE_S32_BE(b8, val) do { \
205 *((int32_t *)(b8)) = (val); \
208 #define _PCM_READ_U16_LE(b8) \
209 INTPCM_T((b8)[0] | (((int8_t)((b8)[1] ^ 0x80)) << 8))
210 #define _PCM_READ_U32_LE(b8) \
211 INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) | \
212 (((int8_t)((b8)[3] ^ 0x80)) << 24))
213 #define _PCM_READ_U16_BE(b8) \
214 INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
215 #define _PCM_READ_U32_BE(b8) \
216 INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
218 #define _PCM_WRITE_U16_LE(bb8, vval) do { \
219 intpcm_t val = (vval); \
220 uint8_t *b8 = (bb8); \
222 b8[1] = (val >> 8) ^ 0x80; \
224 #define _PCM_WRITE_U32_LE(bb8, vval) do { \
225 intpcm_t val = (vval); \
226 uint8_t *b8 = (bb8); \
230 b8[3] = (val >> 24) ^ 0x80; \
232 #define _PCM_WRITE_U16_BE(b8, val) do { \
233 *((uint16_t *)(b8)) = (val) ^ 0x8000; \
235 #define _PCM_WRITE_U32_BE(b8, val) do { \
236 *((uint32_t *)(b8)) = (val) ^ 0x80000000; \
239 #define _PCM_READ_S16_NE(b8) _PCM_READ_S16_BE(b8)
240 #define _PCM_READ_U16_NE(b8) _PCM_READ_U16_BE(b8)
241 #define _PCM_READ_S32_NE(b8) _PCM_READ_S32_BE(b8)
242 #define _PCM_READ_U32_NE(b8) _PCM_READ_U32_BE(b8)
243 #define _PCM_WRITE_S16_NE(b6) _PCM_WRITE_S16_BE(b8)
244 #define _PCM_WRITE_U16_NE(b6) _PCM_WRITE_U16_BE(b8)
245 #define _PCM_WRITE_S32_NE(b6) _PCM_WRITE_S32_BE(b8)
246 #define _PCM_WRITE_U32_NE(b6) _PCM_WRITE_U32_BE(b8)
247 #endif /* LITTLE_ENDIAN */
249 #define _PCM_READ_S24_LE(b8) \
250 INTPCM_T((b8)[0] | ((b8)[1] << 8) | (((int8_t)((b8)[2])) << 16))
251 #define _PCM_READ_S24_BE(b8) \
252 INTPCM_T((b8)[2] | ((b8)[1] << 8) | (((int8_t)((b8)[0])) << 16))
254 #define _PCM_WRITE_S24_LE(bb8, vval) do { \
255 intpcm_t val = (vval); \
256 uint8_t *b8 = (bb8); \
261 #define _PCM_WRITE_S24_BE(bb8, vval) do { \
262 intpcm_t val = (vval); \
263 uint8_t *b8 = (bb8); \
269 #define _PCM_READ_U24_LE(b8) \
270 INTPCM_T((b8)[0] | ((b8)[1] << 8) | \
271 (((int8_t)((b8)[2] ^ 0x80)) << 16))
272 #define _PCM_READ_U24_BE(b8) \
273 INTPCM_T((b8)[2] | ((b8)[1] << 8) | \
274 (((int8_t)((b8)[0] ^ 0x80)) << 16))
276 #define _PCM_WRITE_U24_LE(bb8, vval) do { \
277 intpcm_t val = (vval); \
278 uint8_t *b8 = (bb8); \
281 b8[2] = (val >> 16) ^ 0x80; \
283 #define _PCM_WRITE_U24_BE(bb8, vval) do { \
284 intpcm_t val = (vval); \
285 uint8_t *b8 = (bb8); \
288 b8[0] = (val >> 16) ^ 0x80; \
291 #if BYTE_ORDER == LITTLE_ENDIAN
292 #define _PCM_READ_S24_NE(b8) _PCM_READ_S24_LE(b8)
293 #define _PCM_READ_U24_NE(b8) _PCM_READ_U24_LE(b8)
294 #define _PCM_WRITE_S24_NE(b6) _PCM_WRITE_S24_LE(b8)
295 #define _PCM_WRITE_U24_NE(b6) _PCM_WRITE_U24_LE(b8)
296 #else /* !LITTLE_ENDIAN */
297 #define _PCM_READ_S24_NE(b8) _PCM_READ_S24_BE(b8)
298 #define _PCM_READ_U24_NE(b8) _PCM_READ_U24_BE(b8)
299 #define _PCM_WRITE_S24_NE(b6) _PCM_WRITE_S24_BE(b8)
300 #define _PCM_WRITE_U24_NE(b6) _PCM_WRITE_U24_BE(b8)
301 #endif /* LITTLE_ENDIAN */
303 * 8bit sample is pretty much useless since it doesn't provide
304 * sufficient dynamic range throughout our filtering process.
305 * For the sake of completeness, declare it anyway.
307 #define _PCM_READ_S8_NE(b8) INTPCM_T(*((int8_t *)(b8)))
308 #define _PCM_READ_U8_NE(b8) \
309 INTPCM_T((int8_t)(*((uint8_t *)(b8)) ^ 0x80))
311 #define _PCM_WRITE_S8_NE(b8, val) do { \
312 *((int8_t *)(b8)) = (val); \
314 #define _PCM_WRITE_U8_NE(b8, val) do { \
315 *((uint8_t *)(b8)) = (val) ^ 0x80; \
319 * Common macross. Use this instead of "_", unless we want
320 * the real sample value.
324 #define PCM_READ_S8_NE(b8) _PCM_READ_S8_NE(b8)
325 #define PCM_READ_U8_NE(b8) _PCM_READ_U8_NE(b8)
326 #define PCM_WRITE_S8_NE(b8, val) _PCM_WRITE_S8_NE(b8, val)
327 #define PCM_WRITE_U8_NE(b8, val) _PCM_WRITE_U8_NE(b8, val)
330 #define PCM_READ_S16_LE(b8) _PCM_READ_S16_LE(b8)
331 #define PCM_READ_S16_BE(b8) _PCM_READ_S16_BE(b8)
332 #define PCM_READ_U16_LE(b8) _PCM_READ_U16_LE(b8)
333 #define PCM_READ_U16_BE(b8) _PCM_READ_U16_BE(b8)
335 #define PCM_WRITE_S16_LE(b8, val) _PCM_WRITE_S16_LE(b8, val)
336 #define PCM_WRITE_S16_BE(b8, val) _PCM_WRITE_S16_BE(b8, val)
337 #define PCM_WRITE_U16_LE(b8, val) _PCM_WRITE_U16_LE(b8, val)
338 #define PCM_WRITE_U16_BE(b8, val) _PCM_WRITE_U16_BE(b8, val)
340 #define PCM_READ_S16_NE(b8) _PCM_READ_S16_NE(b8)
341 #define PCM_READ_U16_NE(b8) _PCM_READ_U16_NE(b8)
342 #define PCM_WRITE_S16_NE(b8) _PCM_WRITE_S16_NE(b8)
343 #define PCM_WRITE_U16_NE(b8) _PCM_WRITE_U16_NE(b8)
346 #define PCM_READ_S24_LE(b8) _PCM_READ_S24_LE(b8)
347 #define PCM_READ_S24_BE(b8) _PCM_READ_S24_BE(b8)
348 #define PCM_READ_U24_LE(b8) _PCM_READ_U24_LE(b8)
349 #define PCM_READ_U24_BE(b8) _PCM_READ_U24_BE(b8)
351 #define PCM_WRITE_S24_LE(b8, val) _PCM_WRITE_S24_LE(b8, val)
352 #define PCM_WRITE_S24_BE(b8, val) _PCM_WRITE_S24_BE(b8, val)
353 #define PCM_WRITE_U24_LE(b8, val) _PCM_WRITE_U24_LE(b8, val)
354 #define PCM_WRITE_U24_BE(b8, val) _PCM_WRITE_U24_BE(b8, val)
356 #define PCM_READ_S24_NE(b8) _PCM_READ_S24_NE(b8)
357 #define PCM_READ_U24_NE(b8) _PCM_READ_U24_NE(b8)
358 #define PCM_WRITE_S24_NE(b8) _PCM_WRITE_S24_NE(b8)
359 #define PCM_WRITE_U24_NE(b8) _PCM_WRITE_U24_NE(b8)
363 #define PCM_READ_S32_LE(b8) _PCM_READ_S32_LE(b8)
364 #define PCM_READ_S32_BE(b8) _PCM_READ_S32_BE(b8)
365 #define PCM_READ_U32_LE(b8) _PCM_READ_U32_LE(b8)
366 #define PCM_READ_U32_BE(b8) _PCM_READ_U32_BE(b8)
368 #define PCM_WRITE_S32_LE(b8, val) _PCM_WRITE_S32_LE(b8, val)
369 #define PCM_WRITE_S32_BE(b8, val) _PCM_WRITE_S32_BE(b8, val)
370 #define PCM_WRITE_U32_LE(b8, val) _PCM_WRITE_U32_LE(b8, val)
371 #define PCM_WRITE_U32_BE(b8, val) _PCM_WRITE_U32_BE(b8, val)
373 #define PCM_READ_S32_NE(b8) _PCM_READ_S32_NE(b8)
374 #define PCM_READ_U32_NE(b8) _PCM_READ_U32_NE(b8)
375 #define PCM_WRITE_S32_NE(b8) _PCM_WRITE_S32_NE(b8)
376 #define PCM_WRITE_U32_NE(b8) _PCM_WRITE_U32_NE(b8)
377 #else /* !SND_PCM_64 */
379 * 24bit integer ?!? This is quite unfortunate, eh? Get the fact straight:
382 * 2) 16bit = 96db (close enough)
383 * 3) 24bit = 144db (perfect)
384 * 4) 32bit = 196db (way too much)
385 * 5) Bugs Bunny = Gazillion!@%$Erbzzztt-EINVAL db
386 * Since we're not Bugs Bunny ..uh..err.. avoiding 64bit arithmetic, 24bit
387 * is pretty much sufficient for our signed integer processing.
389 #define PCM_READ_S32_LE(b8) (_PCM_READ_S32_LE(b8) >> PCM_FXSHIFT)
390 #define PCM_READ_S32_BE(b8) (_PCM_READ_S32_BE(b8) >> PCM_FXSHIFT)
391 #define PCM_READ_U32_LE(b8) (_PCM_READ_U32_LE(b8) >> PCM_FXSHIFT)
392 #define PCM_READ_U32_BE(b8) (_PCM_READ_U32_BE(b8) >> PCM_FXSHIFT)
394 #define PCM_READ_S32_NE(b8) (_PCM_READ_S32_NE(b8) >> PCM_FXSHIFT)
395 #define PCM_READ_U32_NE(b8) (_PCM_READ_U32_NE(b8) >> PCM_FXSHIFT)
397 #define PCM_WRITE_S32_LE(b8, val) \
398 _PCM_WRITE_S32_LE(b8, (val) << PCM_FXSHIFT)
399 #define PCM_WRITE_S32_BE(b8, val) \
400 _PCM_WRITE_S32_BE(b8, (val) << PCM_FXSHIFT)
401 #define PCM_WRITE_U32_LE(b8, val) \
402 _PCM_WRITE_U32_LE(b8, (val) << PCM_FXSHIFT)
403 #define PCM_WRITE_U32_BE(b8, val) \
404 _PCM_WRITE_U32_BE(b8, (val) << PCM_FXSHIFT)
406 #define PCM_WRITE_S32_NE(b8, val) \
407 _PCM_WRITE_S32_NE(b8, (val) << PCM_FXSHIFT)
408 #define PCM_WRITE_U32_NE(b8, val) \
409 _PCM_WRITE_U32_NE(b8, (val) << PCM_FXSHIFT)
410 #endif /* SND_PCM_64 */
412 #define PCM_CLAMP_S8(val) \
413 (((val) > PCM_S8_MAX) ? PCM_S8_MAX : \
414 (((val) < PCM_S8_MIN) ? PCM_S8_MIN : (val)))
415 #define PCM_CLAMP_S16(val) \
416 (((val) > PCM_S16_MAX) ? PCM_S16_MAX : \
417 (((val) < PCM_S16_MIN) ? PCM_S16_MIN : (val)))
418 #define PCM_CLAMP_S24(val) \
419 (((val) > PCM_S24_MAX) ? PCM_S24_MAX : \
420 (((val) < PCM_S24_MIN) ? PCM_S24_MIN : (val)))
423 #define PCM_CLAMP_S32(val) \
424 (((val) > PCM_S32_MAX) ? PCM_S32_MAX : \
425 (((val) < PCM_S32_MIN) ? PCM_S32_MIN : (val)))
426 #else /* !SND_PCM_64 */
427 #define PCM_CLAMP_S32(val) \
428 (((val) > PCM_S24_MAX) ? PCM_S32_MAX : \
429 (((val) < PCM_S24_MIN) ? PCM_S32_MIN : \
430 ((val) << PCM_FXSHIFT)))
431 #endif /* SND_PCM_64 */
433 #define PCM_CLAMP_U8(val) PCM_CLAMP_S8(val)
434 #define PCM_CLAMP_U16(val) PCM_CLAMP_S16(val)
435 #define PCM_CLAMP_U24(val) PCM_CLAMP_S24(val)
436 #define PCM_CLAMP_U32(val) PCM_CLAMP_S32(val)
438 #endif /* !_SND_PCM_H_ */