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