xref: /freebsd-src/sys/dev/sound/pcm/pcm.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
190da2b28SAriff Abdullah /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
490da2b28SAriff Abdullah  * Copyright (c) 2006-2009 Ariff Abdullah <ariff@FreeBSD.org>
590da2b28SAriff Abdullah  * All rights reserved.
690da2b28SAriff Abdullah  *
790da2b28SAriff Abdullah  * Redistribution and use in source and binary forms, with or without
890da2b28SAriff Abdullah  * modification, are permitted provided that the following conditions
990da2b28SAriff Abdullah  * are met:
1090da2b28SAriff Abdullah  * 1. Redistributions of source code must retain the above copyright
1190da2b28SAriff Abdullah  *    notice, this list of conditions and the following disclaimer.
1290da2b28SAriff Abdullah  * 2. Redistributions in binary form must reproduce the above copyright
1390da2b28SAriff Abdullah  *    notice, this list of conditions and the following disclaimer in the
1490da2b28SAriff Abdullah  *    documentation and/or other materials provided with the distribution.
1590da2b28SAriff Abdullah  *
1690da2b28SAriff Abdullah  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1790da2b28SAriff Abdullah  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1890da2b28SAriff Abdullah  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1990da2b28SAriff Abdullah  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2090da2b28SAriff Abdullah  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2190da2b28SAriff Abdullah  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2290da2b28SAriff Abdullah  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2390da2b28SAriff Abdullah  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2490da2b28SAriff Abdullah  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2590da2b28SAriff Abdullah  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2690da2b28SAriff Abdullah  * SUCH DAMAGE.
2790da2b28SAriff Abdullah  */
2890da2b28SAriff Abdullah 
2990da2b28SAriff Abdullah #ifndef _SND_PCM_H_
3090da2b28SAriff Abdullah #define _SND_PCM_H_
3190da2b28SAriff Abdullah 
3290da2b28SAriff Abdullah #include <sys/param.h>
3390da2b28SAriff Abdullah 
3490da2b28SAriff Abdullah /*
3590da2b28SAriff Abdullah  * Macros for reading/writing PCM sample / int values from bytes array.
3690da2b28SAriff Abdullah  * Since every process is done using signed integer (and to make our life
3790da2b28SAriff Abdullah  * less miserable), unsigned sample will be converted to its signed
3890da2b28SAriff Abdullah  * counterpart and restored during writing back. To avoid overflow,
3990da2b28SAriff Abdullah  * we truncate 32bit (and only 32bit) samples down to 24bit (see below
4090da2b28SAriff Abdullah  * for the reason), unless SND_PCM_64 is defined.
4190da2b28SAriff Abdullah  */
4290da2b28SAriff Abdullah 
4390da2b28SAriff Abdullah /*
4490da2b28SAriff Abdullah  * Automatically turn on 64bit arithmetic on suitable archs
45e7d939bdSMarcel Moolenaar  * (amd64 64bit, etc..) for wider 32bit samples / integer processing.
4690da2b28SAriff Abdullah  */
4790da2b28SAriff Abdullah #if LONG_BIT >= 64
4890da2b28SAriff Abdullah #undef SND_PCM_64
4990da2b28SAriff Abdullah #define SND_PCM_64	1
5090da2b28SAriff Abdullah #endif
5190da2b28SAriff Abdullah 
5290da2b28SAriff Abdullah typedef int32_t intpcm_t;
5390da2b28SAriff Abdullah 
5490da2b28SAriff Abdullah typedef int32_t intpcm8_t;
5590da2b28SAriff Abdullah typedef int32_t intpcm16_t;
5690da2b28SAriff Abdullah typedef int32_t intpcm24_t;
5790da2b28SAriff Abdullah 
5890da2b28SAriff Abdullah typedef uint32_t uintpcm_t;
5990da2b28SAriff Abdullah 
6090da2b28SAriff Abdullah typedef uint32_t uintpcm8_t;
6190da2b28SAriff Abdullah typedef uint32_t uintpcm16_t;
6290da2b28SAriff Abdullah typedef uint32_t uintpcm24_t;
6390da2b28SAriff Abdullah 
6490da2b28SAriff Abdullah #ifdef SND_PCM_64
6590da2b28SAriff Abdullah typedef int64_t  intpcm32_t;
6690da2b28SAriff Abdullah typedef uint64_t uintpcm32_t;
6790da2b28SAriff Abdullah #else
6890da2b28SAriff Abdullah typedef int32_t  intpcm32_t;
6990da2b28SAriff Abdullah typedef uint32_t uintpcm32_t;
7090da2b28SAriff Abdullah #endif
7190da2b28SAriff Abdullah 
7290da2b28SAriff Abdullah typedef int64_t intpcm64_t;
7390da2b28SAriff Abdullah typedef uint64_t uintpcm64_t;
7490da2b28SAriff Abdullah 
7590da2b28SAriff Abdullah /* 32bit fixed point shift */
7690da2b28SAriff Abdullah #define	PCM_FXSHIFT	8
7790da2b28SAriff Abdullah 
7890da2b28SAriff Abdullah #define PCM_S8_MAX	  0x7f
7990da2b28SAriff Abdullah #define PCM_S8_MIN	 -0x80
8090da2b28SAriff Abdullah #define PCM_S16_MAX	  0x7fff
8190da2b28SAriff Abdullah #define PCM_S16_MIN	 -0x8000
8290da2b28SAriff Abdullah #define PCM_S24_MAX	  0x7fffff
8390da2b28SAriff Abdullah #define PCM_S24_MIN	 -0x800000
8490da2b28SAriff Abdullah #ifdef SND_PCM_64
8590da2b28SAriff Abdullah #if LONG_BIT >= 64
8690da2b28SAriff Abdullah #define PCM_S32_MAX	  0x7fffffffL
8790da2b28SAriff Abdullah #define PCM_S32_MIN	 -0x80000000L
8890da2b28SAriff Abdullah #else
8990da2b28SAriff Abdullah #define PCM_S32_MAX	  0x7fffffffLL
9090da2b28SAriff Abdullah #define PCM_S32_MIN	 -0x80000000LL
9190da2b28SAriff Abdullah #endif
9290da2b28SAriff Abdullah #else
9390da2b28SAriff Abdullah #define PCM_S32_MAX	  0x7fffffff
9490da2b28SAriff Abdullah #define PCM_S32_MIN	(-0x7fffffff - 1)
9590da2b28SAriff Abdullah #endif
9690da2b28SAriff Abdullah 
9790da2b28SAriff Abdullah /* Bytes-per-sample definition */
9890da2b28SAriff Abdullah #define PCM_8_BPS	1
9990da2b28SAriff Abdullah #define PCM_16_BPS	2
10090da2b28SAriff Abdullah #define PCM_24_BPS	3
10190da2b28SAriff Abdullah #define PCM_32_BPS	4
10290da2b28SAriff Abdullah 
10390da2b28SAriff Abdullah #define INTPCM_T(v)	((intpcm_t)(v))
10490da2b28SAriff Abdullah #define INTPCM8_T(v)	((intpcm8_t)(v))
10590da2b28SAriff Abdullah #define INTPCM16_T(v)	((intpcm16_t)(v))
10690da2b28SAriff Abdullah #define INTPCM24_T(v)	((intpcm24_t)(v))
10790da2b28SAriff Abdullah #define INTPCM32_T(v)	((intpcm32_t)(v))
10890da2b28SAriff Abdullah 
10990da2b28SAriff Abdullah #if BYTE_ORDER == LITTLE_ENDIAN
11090da2b28SAriff Abdullah #define _PCM_READ_S16_LE(b8)		INTPCM_T(*((int16_t *)(b8)))
11190da2b28SAriff Abdullah #define _PCM_READ_S32_LE(b8)		INTPCM_T(*((int32_t *)(b8)))
11290da2b28SAriff Abdullah #define _PCM_READ_S16_BE(b8)						\
11390da2b28SAriff Abdullah 	INTPCM_T((b8)[1] | (((int8_t)((b8)[0])) << 8))
11490da2b28SAriff Abdullah #define _PCM_READ_S32_BE(b8)						\
11590da2b28SAriff Abdullah 	INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) |		\
11690da2b28SAriff Abdullah 	    (((int8_t)((b8)[0])) << 24))
11790da2b28SAriff Abdullah 
11890da2b28SAriff Abdullah #define _PCM_WRITE_S16_LE(b8, val)	do {				\
11990da2b28SAriff Abdullah 	*((int16_t *)(b8)) = (val);					\
12090da2b28SAriff Abdullah } while (0)
12190da2b28SAriff Abdullah #define _PCM_WRITE_S32_LE(b8, val)	do {				\
12290da2b28SAriff Abdullah 	*((int32_t *)(b8)) = (val);					\
12390da2b28SAriff Abdullah } while (0)
12490da2b28SAriff Abdullah #define _PCM_WRITE_S16_BE(bb8, vval)	do {				\
12590da2b28SAriff Abdullah 	intpcm_t val = (vval); 						\
12690da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
12790da2b28SAriff Abdullah 	b8[1] = val;							\
12890da2b28SAriff Abdullah 	b8[0] = val >> 8;						\
12990da2b28SAriff Abdullah } while (0)
13090da2b28SAriff Abdullah #define _PCM_WRITE_S32_BE(bb8, vval)	do {				\
13190da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
13290da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
13390da2b28SAriff Abdullah 	b8[3] = val;							\
13490da2b28SAriff Abdullah 	b8[2] = val >> 8;						\
13590da2b28SAriff Abdullah 	b8[1] = val >> 16;						\
13690da2b28SAriff Abdullah 	b8[0] = val >> 24;						\
13790da2b28SAriff Abdullah } while (0)
13890da2b28SAriff Abdullah 
13990da2b28SAriff Abdullah #define _PCM_READ_U16_LE(b8)						\
14090da2b28SAriff Abdullah 	INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
14190da2b28SAriff Abdullah #define _PCM_READ_U32_LE(b8)						\
14290da2b28SAriff Abdullah 	INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
14390da2b28SAriff Abdullah #define _PCM_READ_U16_BE(b8)						\
14490da2b28SAriff Abdullah 	INTPCM_T((b8)[1] | (((int8_t)((b8)[0] ^ 0x80)) << 8))
14590da2b28SAriff Abdullah #define _PCM_READ_U32_BE(b8)						\
14690da2b28SAriff Abdullah 	INTPCM_T((b8)[3] | ((b8)[2] << 8) | ((b8)[1] << 16) |		\
14790da2b28SAriff Abdullah 	    (((int8_t)((b8)[0] ^ 0x80)) << 24))
14890da2b28SAriff Abdullah 
14990da2b28SAriff Abdullah #define _PCM_WRITE_U16_LE(b8, val)	do {				\
15090da2b28SAriff Abdullah 	*((uint16_t *)(b8)) = (val) ^ 0x8000;				\
15190da2b28SAriff Abdullah } while (0)
15290da2b28SAriff Abdullah #define _PCM_WRITE_U32_LE(b8, val)	do {				\
15390da2b28SAriff Abdullah 	*((uint32_t *)(b8)) = (val) ^ 0x80000000;			\
15490da2b28SAriff Abdullah } while (0)
15590da2b28SAriff Abdullah #define _PCM_WRITE_U16_BE(bb8, vval)	do {				\
15690da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
15790da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
15890da2b28SAriff Abdullah 	b8[1] = val;							\
15990da2b28SAriff Abdullah 	b8[0] = (val >> 8) ^ 0x80;					\
16090da2b28SAriff Abdullah } while (0)
16190da2b28SAriff Abdullah #define _PCM_WRITE_U32_BE(bb8, vval)	do {				\
16290da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
16390da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
16490da2b28SAriff Abdullah 	b8[3] = val;							\
16590da2b28SAriff Abdullah 	b8[2] = val >> 8;						\
16690da2b28SAriff Abdullah 	b8[1] = val >> 16;						\
16790da2b28SAriff Abdullah 	b8[0] = (val >> 24) ^ 0x80;					\
16890da2b28SAriff Abdullah } while (0)
16990da2b28SAriff Abdullah 
17090da2b28SAriff Abdullah #define _PCM_READ_S16_NE(b8)	_PCM_READ_S16_LE(b8)
17190da2b28SAriff Abdullah #define _PCM_READ_U16_NE(b8)	_PCM_READ_U16_LE(b8)
17290da2b28SAriff Abdullah #define _PCM_READ_S32_NE(b8)	_PCM_READ_S32_LE(b8)
17390da2b28SAriff Abdullah #define _PCM_READ_U32_NE(b8)	_PCM_READ_U32_LE(b8)
17490da2b28SAriff Abdullah #define _PCM_WRITE_S16_NE(b6)	_PCM_WRITE_S16_LE(b8)
17590da2b28SAriff Abdullah #define _PCM_WRITE_U16_NE(b6)	_PCM_WRITE_U16_LE(b8)
17690da2b28SAriff Abdullah #define _PCM_WRITE_S32_NE(b6)	_PCM_WRITE_S32_LE(b8)
17790da2b28SAriff Abdullah #define _PCM_WRITE_U32_NE(b6)	_PCM_WRITE_U32_LE(b8)
17890da2b28SAriff Abdullah #else	/* !LITTLE_ENDIAN */
17990da2b28SAriff Abdullah #define _PCM_READ_S16_LE(b8)						\
18090da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | (((int8_t)((b8)[1])) << 8))
18190da2b28SAriff Abdullah #define _PCM_READ_S32_LE(b8)						\
18290da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |		\
18390da2b28SAriff Abdullah 	    (((int8_t)((b8)[3])) << 24))
18490da2b28SAriff Abdullah #define _PCM_READ_S16_BE(b8)		INTPCM_T(*((int16_t *)(b8)))
18590da2b28SAriff Abdullah #define _PCM_READ_S32_BE(b8)		INTPCM_T(*((int32_t *)(b8)))
18690da2b28SAriff Abdullah 
18790da2b28SAriff Abdullah #define _PCM_WRITE_S16_LE(bb8, vval)	do {				\
18890da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
18990da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
19090da2b28SAriff Abdullah 	b8[0] = val;							\
19190da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
19290da2b28SAriff Abdullah } while (0)
19390da2b28SAriff Abdullah #define _PCM_WRITE_S32_LE(bb8, vval)	do {				\
19490da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
19590da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
19690da2b28SAriff Abdullah 	b8[0] = val;							\
19790da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
19890da2b28SAriff Abdullah 	b8[2] = val >> 16;						\
19990da2b28SAriff Abdullah 	b8[3] = val >> 24;						\
20090da2b28SAriff Abdullah } while (0)
20190da2b28SAriff Abdullah #define _PCM_WRITE_S16_BE(b8, val)	do {				\
20290da2b28SAriff Abdullah 	*((int16_t *)(b8)) = (val);					\
20390da2b28SAriff Abdullah } while (0)
20490da2b28SAriff Abdullah #define _PCM_WRITE_S32_BE(b8, val)	do {				\
20590da2b28SAriff Abdullah 	*((int32_t *)(b8)) = (val);					\
20690da2b28SAriff Abdullah } while (0)
20790da2b28SAriff Abdullah 
20890da2b28SAriff Abdullah #define _PCM_READ_U16_LE(b8)						\
20990da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | (((int8_t)((b8)[1] ^ 0x80)) << 8))
21090da2b28SAriff Abdullah #define _PCM_READ_U32_LE(b8)						\
21190da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |		\
21290da2b28SAriff Abdullah 	    (((int8_t)((b8)[3] ^ 0x80)) << 24))
21390da2b28SAriff Abdullah #define _PCM_READ_U16_BE(b8)						\
21490da2b28SAriff Abdullah 	INTPCM_T((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
21590da2b28SAriff Abdullah #define _PCM_READ_U32_BE(b8)						\
21690da2b28SAriff Abdullah 	INTPCM_T((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
21790da2b28SAriff Abdullah 
21890da2b28SAriff Abdullah #define _PCM_WRITE_U16_LE(bb8, vval)	do {				\
21990da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
22090da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
22190da2b28SAriff Abdullah 	b8[0] = val;							\
22290da2b28SAriff Abdullah 	b8[1] = (val >> 8) ^ 0x80;					\
22390da2b28SAriff Abdullah } while (0)
22490da2b28SAriff Abdullah #define _PCM_WRITE_U32_LE(bb8, vval)	do {				\
22590da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
22690da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
22790da2b28SAriff Abdullah 	b8[0] = val;							\
22890da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
22990da2b28SAriff Abdullah 	b8[2] = val >> 16;						\
23090da2b28SAriff Abdullah 	b8[3] = (val >> 24) ^ 0x80;					\
23190da2b28SAriff Abdullah } while (0)
23290da2b28SAriff Abdullah #define _PCM_WRITE_U16_BE(b8, val)	do {				\
23390da2b28SAriff Abdullah 	*((uint16_t *)(b8)) = (val) ^ 0x8000;				\
23490da2b28SAriff Abdullah } while (0)
23590da2b28SAriff Abdullah #define _PCM_WRITE_U32_BE(b8, val)	do {				\
23690da2b28SAriff Abdullah 	*((uint32_t *)(b8)) = (val) ^ 0x80000000;			\
23790da2b28SAriff Abdullah } while (0)
23890da2b28SAriff Abdullah 
23990da2b28SAriff Abdullah #define _PCM_READ_S16_NE(b8)	_PCM_READ_S16_BE(b8)
24090da2b28SAriff Abdullah #define _PCM_READ_U16_NE(b8)	_PCM_READ_U16_BE(b8)
24190da2b28SAriff Abdullah #define _PCM_READ_S32_NE(b8)	_PCM_READ_S32_BE(b8)
24290da2b28SAriff Abdullah #define _PCM_READ_U32_NE(b8)	_PCM_READ_U32_BE(b8)
24390da2b28SAriff Abdullah #define _PCM_WRITE_S16_NE(b6)	_PCM_WRITE_S16_BE(b8)
24490da2b28SAriff Abdullah #define _PCM_WRITE_U16_NE(b6)	_PCM_WRITE_U16_BE(b8)
24590da2b28SAriff Abdullah #define _PCM_WRITE_S32_NE(b6)	_PCM_WRITE_S32_BE(b8)
24690da2b28SAriff Abdullah #define _PCM_WRITE_U32_NE(b6)	_PCM_WRITE_U32_BE(b8)
24790da2b28SAriff Abdullah #endif	/* LITTLE_ENDIAN */
24890da2b28SAriff Abdullah 
24990da2b28SAriff Abdullah #define _PCM_READ_S24_LE(b8)						\
25090da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | ((b8)[1] << 8) | (((int8_t)((b8)[2])) << 16))
25190da2b28SAriff Abdullah #define _PCM_READ_S24_BE(b8)						\
25290da2b28SAriff Abdullah 	INTPCM_T((b8)[2] | ((b8)[1] << 8) | (((int8_t)((b8)[0])) << 16))
25390da2b28SAriff Abdullah 
25490da2b28SAriff Abdullah #define _PCM_WRITE_S24_LE(bb8, vval)	do {				\
25590da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
25690da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
25790da2b28SAriff Abdullah 	b8[0] = val;							\
25890da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
25990da2b28SAriff Abdullah 	b8[2] = val >> 16;						\
26090da2b28SAriff Abdullah } while (0)
26190da2b28SAriff Abdullah #define _PCM_WRITE_S24_BE(bb8, vval)	do {				\
26290da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
26390da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
26490da2b28SAriff Abdullah 	b8[2] = val;							\
26590da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
26690da2b28SAriff Abdullah 	b8[0] = val >> 16;						\
26790da2b28SAriff Abdullah } while (0)
26890da2b28SAriff Abdullah 
26990da2b28SAriff Abdullah #define _PCM_READ_U24_LE(b8)						\
27090da2b28SAriff Abdullah 	INTPCM_T((b8)[0] | ((b8)[1] << 8) |				\
27190da2b28SAriff Abdullah 	    (((int8_t)((b8)[2] ^ 0x80)) << 16))
27290da2b28SAriff Abdullah #define _PCM_READ_U24_BE(b8)						\
27390da2b28SAriff Abdullah 	INTPCM_T((b8)[2] | ((b8)[1] << 8) |				\
27490da2b28SAriff Abdullah 	    (((int8_t)((b8)[0] ^ 0x80)) << 16))
27590da2b28SAriff Abdullah 
27690da2b28SAriff Abdullah #define _PCM_WRITE_U24_LE(bb8, vval)	do {				\
27790da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
27890da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
27990da2b28SAriff Abdullah 	b8[0] = val;							\
28090da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
28190da2b28SAriff Abdullah 	b8[2] = (val >> 16) ^ 0x80;					\
28290da2b28SAriff Abdullah } while (0)
28390da2b28SAriff Abdullah #define _PCM_WRITE_U24_BE(bb8, vval)	do {				\
28490da2b28SAriff Abdullah 	intpcm_t val = (vval);						\
28590da2b28SAriff Abdullah 	uint8_t *b8 = (bb8);						\
28690da2b28SAriff Abdullah 	b8[2] = val;							\
28790da2b28SAriff Abdullah 	b8[1] = val >> 8;						\
28890da2b28SAriff Abdullah 	b8[0] = (val >> 16) ^ 0x80;					\
28990da2b28SAriff Abdullah } while (0)
29090da2b28SAriff Abdullah 
29190da2b28SAriff Abdullah #if BYTE_ORDER == LITTLE_ENDIAN
29290da2b28SAriff Abdullah #define _PCM_READ_S24_NE(b8)	_PCM_READ_S24_LE(b8)
29390da2b28SAriff Abdullah #define _PCM_READ_U24_NE(b8)	_PCM_READ_U24_LE(b8)
29490da2b28SAriff Abdullah #define _PCM_WRITE_S24_NE(b6)	_PCM_WRITE_S24_LE(b8)
29590da2b28SAriff Abdullah #define _PCM_WRITE_U24_NE(b6)	_PCM_WRITE_U24_LE(b8)
29690da2b28SAriff Abdullah #else	/* !LITTLE_ENDIAN */
29790da2b28SAriff Abdullah #define _PCM_READ_S24_NE(b8)	_PCM_READ_S24_BE(b8)
29890da2b28SAriff Abdullah #define _PCM_READ_U24_NE(b8)	_PCM_READ_U24_BE(b8)
29990da2b28SAriff Abdullah #define _PCM_WRITE_S24_NE(b6)	_PCM_WRITE_S24_BE(b8)
30090da2b28SAriff Abdullah #define _PCM_WRITE_U24_NE(b6)	_PCM_WRITE_U24_BE(b8)
30190da2b28SAriff Abdullah #endif	/* LITTLE_ENDIAN */
30290da2b28SAriff Abdullah /*
30390da2b28SAriff Abdullah  * 8bit sample is pretty much useless since it doesn't provide
30490da2b28SAriff Abdullah  * sufficient dynamic range throughout our filtering process.
30590da2b28SAriff Abdullah  * For the sake of completeness, declare it anyway.
30690da2b28SAriff Abdullah  */
30790da2b28SAriff Abdullah #define _PCM_READ_S8_NE(b8)		INTPCM_T(*((int8_t *)(b8)))
30890da2b28SAriff Abdullah #define _PCM_READ_U8_NE(b8)						\
30990da2b28SAriff Abdullah 	INTPCM_T((int8_t)(*((uint8_t *)(b8)) ^ 0x80))
31090da2b28SAriff Abdullah 
31190da2b28SAriff Abdullah #define _PCM_WRITE_S8_NE(b8, val)	do {				\
31290da2b28SAriff Abdullah 	*((int8_t *)(b8)) = (val);					\
31390da2b28SAriff Abdullah } while (0)
31490da2b28SAriff Abdullah #define _PCM_WRITE_U8_NE(b8, val)	do {				\
31590da2b28SAriff Abdullah 	*((uint8_t *)(b8)) = (val) ^ 0x80;				\
31690da2b28SAriff Abdullah } while (0)
31790da2b28SAriff Abdullah 
31890da2b28SAriff Abdullah /*
31990da2b28SAriff Abdullah  * Common macross. Use this instead of "_", unless we want
32090da2b28SAriff Abdullah  * the real sample value.
32190da2b28SAriff Abdullah  */
32290da2b28SAriff Abdullah 
32390da2b28SAriff Abdullah /* 8bit */
32490da2b28SAriff Abdullah #define PCM_READ_S8_NE(b8)		_PCM_READ_S8_NE(b8)
32590da2b28SAriff Abdullah #define PCM_READ_U8_NE(b8)		_PCM_READ_U8_NE(b8)
32690da2b28SAriff Abdullah #define PCM_WRITE_S8_NE(b8, val)	_PCM_WRITE_S8_NE(b8, val)
32790da2b28SAriff Abdullah #define PCM_WRITE_U8_NE(b8, val)	_PCM_WRITE_U8_NE(b8, val)
32890da2b28SAriff Abdullah 
32990da2b28SAriff Abdullah /* 16bit */
33090da2b28SAriff Abdullah #define PCM_READ_S16_LE(b8)		_PCM_READ_S16_LE(b8)
33190da2b28SAriff Abdullah #define PCM_READ_S16_BE(b8)		_PCM_READ_S16_BE(b8)
33290da2b28SAriff Abdullah #define PCM_READ_U16_LE(b8)		_PCM_READ_U16_LE(b8)
33390da2b28SAriff Abdullah #define PCM_READ_U16_BE(b8)		_PCM_READ_U16_BE(b8)
33490da2b28SAriff Abdullah 
33590da2b28SAriff Abdullah #define PCM_WRITE_S16_LE(b8, val)	_PCM_WRITE_S16_LE(b8, val)
33690da2b28SAriff Abdullah #define PCM_WRITE_S16_BE(b8, val)	_PCM_WRITE_S16_BE(b8, val)
33790da2b28SAriff Abdullah #define PCM_WRITE_U16_LE(b8, val)	_PCM_WRITE_U16_LE(b8, val)
33890da2b28SAriff Abdullah #define PCM_WRITE_U16_BE(b8, val)	_PCM_WRITE_U16_BE(b8, val)
33990da2b28SAriff Abdullah 
34090da2b28SAriff Abdullah #define PCM_READ_S16_NE(b8)		_PCM_READ_S16_NE(b8)
34190da2b28SAriff Abdullah #define PCM_READ_U16_NE(b8)		_PCM_READ_U16_NE(b8)
34290da2b28SAriff Abdullah #define PCM_WRITE_S16_NE(b8)		_PCM_WRITE_S16_NE(b8)
34390da2b28SAriff Abdullah #define PCM_WRITE_U16_NE(b8)		_PCM_WRITE_U16_NE(b8)
34490da2b28SAriff Abdullah 
34590da2b28SAriff Abdullah /* 24bit */
34690da2b28SAriff Abdullah #define PCM_READ_S24_LE(b8)		_PCM_READ_S24_LE(b8)
34790da2b28SAriff Abdullah #define PCM_READ_S24_BE(b8)		_PCM_READ_S24_BE(b8)
34890da2b28SAriff Abdullah #define PCM_READ_U24_LE(b8)		_PCM_READ_U24_LE(b8)
34990da2b28SAriff Abdullah #define PCM_READ_U24_BE(b8)		_PCM_READ_U24_BE(b8)
35090da2b28SAriff Abdullah 
35190da2b28SAriff Abdullah #define PCM_WRITE_S24_LE(b8, val)	_PCM_WRITE_S24_LE(b8, val)
35290da2b28SAriff Abdullah #define PCM_WRITE_S24_BE(b8, val)	_PCM_WRITE_S24_BE(b8, val)
35390da2b28SAriff Abdullah #define PCM_WRITE_U24_LE(b8, val)	_PCM_WRITE_U24_LE(b8, val)
35490da2b28SAriff Abdullah #define PCM_WRITE_U24_BE(b8, val)	_PCM_WRITE_U24_BE(b8, val)
35590da2b28SAriff Abdullah 
35690da2b28SAriff Abdullah #define PCM_READ_S24_NE(b8)		_PCM_READ_S24_NE(b8)
35790da2b28SAriff Abdullah #define PCM_READ_U24_NE(b8)		_PCM_READ_U24_NE(b8)
35890da2b28SAriff Abdullah #define PCM_WRITE_S24_NE(b8)		_PCM_WRITE_S24_NE(b8)
35990da2b28SAriff Abdullah #define PCM_WRITE_U24_NE(b8)		_PCM_WRITE_U24_NE(b8)
36090da2b28SAriff Abdullah 
36190da2b28SAriff Abdullah /* 32bit */
36290da2b28SAriff Abdullah #ifdef SND_PCM_64
36390da2b28SAriff Abdullah #define PCM_READ_S32_LE(b8)		_PCM_READ_S32_LE(b8)
36490da2b28SAriff Abdullah #define PCM_READ_S32_BE(b8)		_PCM_READ_S32_BE(b8)
36590da2b28SAriff Abdullah #define PCM_READ_U32_LE(b8)		_PCM_READ_U32_LE(b8)
36690da2b28SAriff Abdullah #define PCM_READ_U32_BE(b8)		_PCM_READ_U32_BE(b8)
36790da2b28SAriff Abdullah 
36890da2b28SAriff Abdullah #define PCM_WRITE_S32_LE(b8, val)	_PCM_WRITE_S32_LE(b8, val)
36990da2b28SAriff Abdullah #define PCM_WRITE_S32_BE(b8, val)	_PCM_WRITE_S32_BE(b8, val)
37090da2b28SAriff Abdullah #define PCM_WRITE_U32_LE(b8, val)	_PCM_WRITE_U32_LE(b8, val)
37190da2b28SAriff Abdullah #define PCM_WRITE_U32_BE(b8, val)	_PCM_WRITE_U32_BE(b8, val)
37290da2b28SAriff Abdullah 
37390da2b28SAriff Abdullah #define PCM_READ_S32_NE(b8)		_PCM_READ_S32_NE(b8)
37490da2b28SAriff Abdullah #define PCM_READ_U32_NE(b8)		_PCM_READ_U32_NE(b8)
37590da2b28SAriff Abdullah #define PCM_WRITE_S32_NE(b8)		_PCM_WRITE_S32_NE(b8)
37690da2b28SAriff Abdullah #define PCM_WRITE_U32_NE(b8)		_PCM_WRITE_U32_NE(b8)
37790da2b28SAriff Abdullah #else	/* !SND_PCM_64 */
37890da2b28SAriff Abdullah /*
37990da2b28SAriff Abdullah  * 24bit integer ?!? This is quite unfortunate, eh? Get the fact straight:
38090da2b28SAriff Abdullah  * Dynamic range for:
38190da2b28SAriff Abdullah  *	1) Human =~ 140db
38290da2b28SAriff Abdullah  *	2) 16bit = 96db (close enough)
38390da2b28SAriff Abdullah  *	3) 24bit = 144db (perfect)
38490da2b28SAriff Abdullah  *	4) 32bit = 196db (way too much)
38590da2b28SAriff Abdullah  *	5) Bugs Bunny = Gazillion!@%$Erbzzztt-EINVAL db
38690da2b28SAriff Abdullah  * Since we're not Bugs Bunny ..uh..err.. avoiding 64bit arithmetic, 24bit
38790da2b28SAriff Abdullah  * is pretty much sufficient for our signed integer processing.
38890da2b28SAriff Abdullah  */
38990da2b28SAriff Abdullah #define PCM_READ_S32_LE(b8)		(_PCM_READ_S32_LE(b8) >> PCM_FXSHIFT)
39090da2b28SAriff Abdullah #define PCM_READ_S32_BE(b8)		(_PCM_READ_S32_BE(b8) >> PCM_FXSHIFT)
39190da2b28SAriff Abdullah #define PCM_READ_U32_LE(b8)		(_PCM_READ_U32_LE(b8) >> PCM_FXSHIFT)
39290da2b28SAriff Abdullah #define PCM_READ_U32_BE(b8)		(_PCM_READ_U32_BE(b8) >> PCM_FXSHIFT)
39390da2b28SAriff Abdullah 
39490da2b28SAriff Abdullah #define PCM_READ_S32_NE(b8)		(_PCM_READ_S32_NE(b8) >> PCM_FXSHIFT)
39590da2b28SAriff Abdullah #define PCM_READ_U32_NE(b8)		(_PCM_READ_U32_NE(b8) >> PCM_FXSHIFT)
39690da2b28SAriff Abdullah 
39790da2b28SAriff Abdullah #define PCM_WRITE_S32_LE(b8, val)					\
39890da2b28SAriff Abdullah 			_PCM_WRITE_S32_LE(b8, (val) << PCM_FXSHIFT)
39990da2b28SAriff Abdullah #define PCM_WRITE_S32_BE(b8, val)					\
40090da2b28SAriff Abdullah 			_PCM_WRITE_S32_BE(b8, (val) << PCM_FXSHIFT)
40190da2b28SAriff Abdullah #define PCM_WRITE_U32_LE(b8, val)					\
40290da2b28SAriff Abdullah 			_PCM_WRITE_U32_LE(b8, (val) << PCM_FXSHIFT)
40390da2b28SAriff Abdullah #define PCM_WRITE_U32_BE(b8, val)					\
40490da2b28SAriff Abdullah 			_PCM_WRITE_U32_BE(b8, (val) << PCM_FXSHIFT)
40590da2b28SAriff Abdullah 
40690da2b28SAriff Abdullah #define PCM_WRITE_S32_NE(b8, val)					\
40790da2b28SAriff Abdullah 			_PCM_WRITE_S32_NE(b8, (val) << PCM_FXSHIFT)
40890da2b28SAriff Abdullah #define PCM_WRITE_U32_NE(b8, val)					\
40990da2b28SAriff Abdullah 			_PCM_WRITE_U32_NE(b8, (val) << PCM_FXSHIFT)
41090da2b28SAriff Abdullah #endif	/* SND_PCM_64 */
41190da2b28SAriff Abdullah 
41290da2b28SAriff Abdullah #define PCM_CLAMP_S8(val)						\
41390da2b28SAriff Abdullah 			(((val) > PCM_S8_MAX) ? PCM_S8_MAX :		\
41490da2b28SAriff Abdullah 			 (((val) < PCM_S8_MIN) ? PCM_S8_MIN : (val)))
41590da2b28SAriff Abdullah #define PCM_CLAMP_S16(val)						\
41690da2b28SAriff Abdullah 			(((val) > PCM_S16_MAX) ? PCM_S16_MAX :		\
41790da2b28SAriff Abdullah 			 (((val) < PCM_S16_MIN) ? PCM_S16_MIN : (val)))
41890da2b28SAriff Abdullah #define PCM_CLAMP_S24(val)						\
41990da2b28SAriff Abdullah 			(((val) > PCM_S24_MAX) ? PCM_S24_MAX :		\
42090da2b28SAriff Abdullah 			 (((val) < PCM_S24_MIN) ? PCM_S24_MIN : (val)))
42190da2b28SAriff Abdullah 
42290da2b28SAriff Abdullah #ifdef SND_PCM_64
42390da2b28SAriff Abdullah #define PCM_CLAMP_S32(val)						\
42490da2b28SAriff Abdullah 			(((val) > PCM_S32_MAX) ? PCM_S32_MAX :		\
42590da2b28SAriff Abdullah 			 (((val) < PCM_S32_MIN) ? PCM_S32_MIN : (val)))
42690da2b28SAriff Abdullah #else	/* !SND_PCM_64 */
42790da2b28SAriff Abdullah #define PCM_CLAMP_S32(val)						\
42890da2b28SAriff Abdullah 			(((val) > PCM_S24_MAX) ? PCM_S32_MAX :		\
42990da2b28SAriff Abdullah 			 (((val) < PCM_S24_MIN) ? PCM_S32_MIN :		\
43090da2b28SAriff Abdullah 			 ((val) << PCM_FXSHIFT)))
43190da2b28SAriff Abdullah #endif	/* SND_PCM_64 */
43290da2b28SAriff Abdullah 
43390da2b28SAriff Abdullah #define PCM_CLAMP_U8(val)	PCM_CLAMP_S8(val)
43490da2b28SAriff Abdullah #define PCM_CLAMP_U16(val)	PCM_CLAMP_S16(val)
43590da2b28SAriff Abdullah #define PCM_CLAMP_U24(val)	PCM_CLAMP_S24(val)
43690da2b28SAriff Abdullah #define PCM_CLAMP_U32(val)	PCM_CLAMP_S32(val)
43790da2b28SAriff Abdullah 
43890da2b28SAriff Abdullah #endif	/* !_SND_PCM_H_ */
439