2 * PCM Interface - misc routines
3 * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "pcm_local.h"
31 * \brief Return sign info for a PCM sample linear format
32 * \param format Format
33 * \return 0 unsigned, 1 signed, a negative error code if format is not linear
35 int snd_pcm_format_signed(snd_pcm_format_t format)
38 case SNDRV_PCM_FORMAT_S8:
39 case SNDRV_PCM_FORMAT_S16_LE:
40 case SNDRV_PCM_FORMAT_S16_BE:
41 case SNDRV_PCM_FORMAT_S24_LE:
42 case SNDRV_PCM_FORMAT_S24_BE:
43 case SNDRV_PCM_FORMAT_S32_LE:
44 case SNDRV_PCM_FORMAT_S32_BE:
45 case SNDRV_PCM_FORMAT_S24_3LE:
46 case SNDRV_PCM_FORMAT_S24_3BE:
47 case SNDRV_PCM_FORMAT_S20_3LE:
48 case SNDRV_PCM_FORMAT_S20_3BE:
49 case SNDRV_PCM_FORMAT_S18_3LE:
50 case SNDRV_PCM_FORMAT_S18_3BE:
52 case SNDRV_PCM_FORMAT_U8:
53 case SNDRV_PCM_FORMAT_U16_LE:
54 case SNDRV_PCM_FORMAT_U16_BE:
55 case SNDRV_PCM_FORMAT_U24_LE:
56 case SNDRV_PCM_FORMAT_U24_BE:
57 case SNDRV_PCM_FORMAT_U32_LE:
58 case SNDRV_PCM_FORMAT_U32_BE:
59 case SNDRV_PCM_FORMAT_U24_3LE:
60 case SNDRV_PCM_FORMAT_U24_3BE:
61 case SNDRV_PCM_FORMAT_U20_3LE:
62 case SNDRV_PCM_FORMAT_U20_3BE:
63 case SNDRV_PCM_FORMAT_U18_3LE:
64 case SNDRV_PCM_FORMAT_U18_3BE:
65 case SNDRV_PCM_FORMAT_DSD_U8:
66 case SNDRV_PCM_FORMAT_DSD_U16_LE:
67 case SNDRV_PCM_FORMAT_DSD_U32_LE:
75 * \brief Return sign info for a PCM sample linear format
76 * \param format Format
77 * \return 0 signed, 1 unsigned, a negative error code if format is not linear
79 int snd_pcm_format_unsigned(snd_pcm_format_t format)
83 val = snd_pcm_format_signed(format);
90 * \brief Return linear info for a PCM sample format
91 * \param format Format
92 * \return 0 non linear, 1 linear
94 int snd_pcm_format_linear(snd_pcm_format_t format)
96 return snd_pcm_format_signed(format) >= 0;
100 * \brief Return float info for a PCM sample format
101 * \param format Format
102 * \return 0 non float, 1 float
104 int snd_pcm_format_float(snd_pcm_format_t format)
107 case SNDRV_PCM_FORMAT_FLOAT_LE:
108 case SNDRV_PCM_FORMAT_FLOAT_BE:
109 case SNDRV_PCM_FORMAT_FLOAT64_LE:
110 case SNDRV_PCM_FORMAT_FLOAT64_BE:
118 * \brief Return endian info for a PCM sample format
119 * \param format Format
120 * \return 0 big endian, 1 little endian, a negative error code if endian independent
122 int snd_pcm_format_little_endian(snd_pcm_format_t format)
125 case SNDRV_PCM_FORMAT_S16_LE:
126 case SNDRV_PCM_FORMAT_U16_LE:
127 case SNDRV_PCM_FORMAT_S24_LE:
128 case SNDRV_PCM_FORMAT_U24_LE:
129 case SNDRV_PCM_FORMAT_S32_LE:
130 case SNDRV_PCM_FORMAT_U32_LE:
131 case SNDRV_PCM_FORMAT_FLOAT_LE:
132 case SNDRV_PCM_FORMAT_FLOAT64_LE:
133 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
134 case SNDRV_PCM_FORMAT_S24_3LE:
135 case SNDRV_PCM_FORMAT_S20_3LE:
136 case SNDRV_PCM_FORMAT_S18_3LE:
137 case SNDRV_PCM_FORMAT_U24_3LE:
138 case SNDRV_PCM_FORMAT_U20_3LE:
139 case SNDRV_PCM_FORMAT_U18_3LE:
141 case SNDRV_PCM_FORMAT_S16_BE:
142 case SNDRV_PCM_FORMAT_U16_BE:
143 case SNDRV_PCM_FORMAT_S24_BE:
144 case SNDRV_PCM_FORMAT_U24_BE:
145 case SNDRV_PCM_FORMAT_S32_BE:
146 case SNDRV_PCM_FORMAT_U32_BE:
147 case SNDRV_PCM_FORMAT_FLOAT_BE:
148 case SNDRV_PCM_FORMAT_FLOAT64_BE:
149 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
150 case SNDRV_PCM_FORMAT_S24_3BE:
151 case SNDRV_PCM_FORMAT_S20_3BE:
152 case SNDRV_PCM_FORMAT_S18_3BE:
153 case SNDRV_PCM_FORMAT_U24_3BE:
154 case SNDRV_PCM_FORMAT_U20_3BE:
155 case SNDRV_PCM_FORMAT_U18_3BE:
156 case SNDRV_PCM_FORMAT_DSD_U8:
157 case SNDRV_PCM_FORMAT_DSD_U16_LE:
158 case SNDRV_PCM_FORMAT_DSD_U32_LE:
166 * \brief Return endian info for a PCM sample format
167 * \param format Format
168 * \return 0 little endian, 1 big endian, a negative error code if endian independent
170 int snd_pcm_format_big_endian(snd_pcm_format_t format)
174 val = snd_pcm_format_little_endian(format);
181 * \brief Return endian info for a PCM sample format
182 * \param format Format
183 * \return 0 swapped, 1 CPU endian, a negative error code if endian independent
185 int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
187 #ifdef SNDRV_LITTLE_ENDIAN
188 return snd_pcm_format_little_endian(format);
190 return snd_pcm_format_big_endian(format);
195 * \brief Return nominal bits per a PCM sample
196 * \param format Sample format
197 * \return bits per sample, a negative error code if not applicable
199 int snd_pcm_format_width(snd_pcm_format_t format)
202 case SNDRV_PCM_FORMAT_S8:
203 case SNDRV_PCM_FORMAT_U8:
204 case SNDRV_PCM_FORMAT_DSD_U8:
206 case SNDRV_PCM_FORMAT_S16_LE:
207 case SNDRV_PCM_FORMAT_S16_BE:
208 case SNDRV_PCM_FORMAT_U16_LE:
209 case SNDRV_PCM_FORMAT_U16_BE:
210 case SNDRV_PCM_FORMAT_DSD_U16_LE:
212 case SNDRV_PCM_FORMAT_S18_3LE:
213 case SNDRV_PCM_FORMAT_S18_3BE:
214 case SNDRV_PCM_FORMAT_U18_3LE:
215 case SNDRV_PCM_FORMAT_U18_3BE:
217 case SNDRV_PCM_FORMAT_S20_3LE:
218 case SNDRV_PCM_FORMAT_S20_3BE:
219 case SNDRV_PCM_FORMAT_U20_3LE:
220 case SNDRV_PCM_FORMAT_U20_3BE:
222 case SNDRV_PCM_FORMAT_S24_LE:
223 case SNDRV_PCM_FORMAT_S24_BE:
224 case SNDRV_PCM_FORMAT_U24_LE:
225 case SNDRV_PCM_FORMAT_U24_BE:
226 case SNDRV_PCM_FORMAT_S24_3LE:
227 case SNDRV_PCM_FORMAT_S24_3BE:
228 case SNDRV_PCM_FORMAT_U24_3LE:
229 case SNDRV_PCM_FORMAT_U24_3BE:
231 case SNDRV_PCM_FORMAT_S32_LE:
232 case SNDRV_PCM_FORMAT_S32_BE:
233 case SNDRV_PCM_FORMAT_U32_LE:
234 case SNDRV_PCM_FORMAT_U32_BE:
235 case SNDRV_PCM_FORMAT_FLOAT_LE:
236 case SNDRV_PCM_FORMAT_FLOAT_BE:
237 case SNDRV_PCM_FORMAT_DSD_U32_LE:
239 case SNDRV_PCM_FORMAT_FLOAT64_LE:
240 case SNDRV_PCM_FORMAT_FLOAT64_BE:
242 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
243 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
245 case SNDRV_PCM_FORMAT_MU_LAW:
246 case SNDRV_PCM_FORMAT_A_LAW:
248 case SNDRV_PCM_FORMAT_IMA_ADPCM:
256 * \brief Return bits needed to store a PCM sample
257 * \param format Sample format
258 * \return bits per sample, a negative error code if not applicable
260 int snd_pcm_format_physical_width(snd_pcm_format_t format)
263 case SNDRV_PCM_FORMAT_S8:
264 case SNDRV_PCM_FORMAT_U8:
265 case SNDRV_PCM_FORMAT_DSD_U8:
267 case SNDRV_PCM_FORMAT_S16_LE:
268 case SNDRV_PCM_FORMAT_S16_BE:
269 case SNDRV_PCM_FORMAT_U16_LE:
270 case SNDRV_PCM_FORMAT_U16_BE:
271 case SNDRV_PCM_FORMAT_DSD_U16_LE:
273 case SNDRV_PCM_FORMAT_S18_3LE:
274 case SNDRV_PCM_FORMAT_S18_3BE:
275 case SNDRV_PCM_FORMAT_U18_3LE:
276 case SNDRV_PCM_FORMAT_U18_3BE:
277 case SNDRV_PCM_FORMAT_S20_3LE:
278 case SNDRV_PCM_FORMAT_S20_3BE:
279 case SNDRV_PCM_FORMAT_U20_3LE:
280 case SNDRV_PCM_FORMAT_U20_3BE:
281 case SNDRV_PCM_FORMAT_S24_3LE:
282 case SNDRV_PCM_FORMAT_S24_3BE:
283 case SNDRV_PCM_FORMAT_U24_3LE:
284 case SNDRV_PCM_FORMAT_U24_3BE:
286 case SNDRV_PCM_FORMAT_S24_LE:
287 case SNDRV_PCM_FORMAT_S24_BE:
288 case SNDRV_PCM_FORMAT_U24_LE:
289 case SNDRV_PCM_FORMAT_U24_BE:
290 case SNDRV_PCM_FORMAT_S32_LE:
291 case SNDRV_PCM_FORMAT_S32_BE:
292 case SNDRV_PCM_FORMAT_U32_LE:
293 case SNDRV_PCM_FORMAT_U32_BE:
294 case SNDRV_PCM_FORMAT_FLOAT_LE:
295 case SNDRV_PCM_FORMAT_FLOAT_BE:
296 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
297 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
298 case SNDRV_PCM_FORMAT_DSD_U32_LE:
300 case SNDRV_PCM_FORMAT_FLOAT64_LE:
301 case SNDRV_PCM_FORMAT_FLOAT64_BE:
303 case SNDRV_PCM_FORMAT_MU_LAW:
304 case SNDRV_PCM_FORMAT_A_LAW:
306 case SNDRV_PCM_FORMAT_IMA_ADPCM:
314 * \brief Return bytes needed to store a quantity of PCM sample
315 * \param format Sample format
316 * \param samples Samples count
317 * \return bytes needed, a negative error code if not integer or unknown
319 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
322 case SNDRV_PCM_FORMAT_S8:
323 case SNDRV_PCM_FORMAT_U8:
324 case SNDRV_PCM_FORMAT_DSD_U8:
326 case SNDRV_PCM_FORMAT_S16_LE:
327 case SNDRV_PCM_FORMAT_S16_BE:
328 case SNDRV_PCM_FORMAT_U16_LE:
329 case SNDRV_PCM_FORMAT_U16_BE:
330 case SNDRV_PCM_FORMAT_DSD_U16_LE:
332 case SNDRV_PCM_FORMAT_S18_3LE:
333 case SNDRV_PCM_FORMAT_S18_3BE:
334 case SNDRV_PCM_FORMAT_U18_3LE:
335 case SNDRV_PCM_FORMAT_U18_3BE:
336 case SNDRV_PCM_FORMAT_S20_3LE:
337 case SNDRV_PCM_FORMAT_S20_3BE:
338 case SNDRV_PCM_FORMAT_U20_3LE:
339 case SNDRV_PCM_FORMAT_U20_3BE:
340 case SNDRV_PCM_FORMAT_S24_3LE:
341 case SNDRV_PCM_FORMAT_S24_3BE:
342 case SNDRV_PCM_FORMAT_U24_3LE:
343 case SNDRV_PCM_FORMAT_U24_3BE:
345 case SNDRV_PCM_FORMAT_S24_LE:
346 case SNDRV_PCM_FORMAT_S24_BE:
347 case SNDRV_PCM_FORMAT_U24_LE:
348 case SNDRV_PCM_FORMAT_U24_BE:
349 case SNDRV_PCM_FORMAT_S32_LE:
350 case SNDRV_PCM_FORMAT_S32_BE:
351 case SNDRV_PCM_FORMAT_U32_LE:
352 case SNDRV_PCM_FORMAT_U32_BE:
353 case SNDRV_PCM_FORMAT_FLOAT_LE:
354 case SNDRV_PCM_FORMAT_FLOAT_BE:
355 case SNDRV_PCM_FORMAT_DSD_U32_LE:
357 case SNDRV_PCM_FORMAT_FLOAT64_LE:
358 case SNDRV_PCM_FORMAT_FLOAT64_BE:
360 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
361 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
363 case SNDRV_PCM_FORMAT_MU_LAW:
364 case SNDRV_PCM_FORMAT_A_LAW:
366 case SNDRV_PCM_FORMAT_IMA_ADPCM:
377 * \brief Return 64 bit expressing silence for a PCM sample format
378 * \param format Sample format
379 * \return silence 64 bit word
381 u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
384 case SNDRV_PCM_FORMAT_S8:
385 case SNDRV_PCM_FORMAT_S16_LE:
386 case SNDRV_PCM_FORMAT_S16_BE:
387 case SNDRV_PCM_FORMAT_S24_LE:
388 case SNDRV_PCM_FORMAT_S24_BE:
389 case SNDRV_PCM_FORMAT_S32_LE:
390 case SNDRV_PCM_FORMAT_S32_BE:
391 case SNDRV_PCM_FORMAT_S24_3LE:
392 case SNDRV_PCM_FORMAT_S24_3BE:
393 case SNDRV_PCM_FORMAT_S20_3LE:
394 case SNDRV_PCM_FORMAT_S20_3BE:
395 case SNDRV_PCM_FORMAT_S18_3LE:
396 case SNDRV_PCM_FORMAT_S18_3BE:
398 case SNDRV_PCM_FORMAT_U8:
399 return 0x8080808080808080ULL;
400 case SNDRV_PCM_FORMAT_DSD_U8:
401 case SNDRV_PCM_FORMAT_DSD_U16_LE:
402 case SNDRV_PCM_FORMAT_DSD_U32_LE:
403 return 0x6969696969696969ULL;
404 #ifdef SNDRV_LITTLE_ENDIAN
405 case SNDRV_PCM_FORMAT_U16_LE:
406 return 0x8000800080008000ULL;
407 case SNDRV_PCM_FORMAT_U24_LE:
408 return 0x0080000000800000ULL;
409 case SNDRV_PCM_FORMAT_U32_LE:
410 return 0x8000000080000000ULL;
411 case SNDRV_PCM_FORMAT_U16_BE:
412 return 0x0080008000800080ULL;
413 case SNDRV_PCM_FORMAT_U24_BE:
414 return 0x0000800000008000ULL;
415 case SNDRV_PCM_FORMAT_U32_BE:
416 return 0x0000008000000080ULL;
417 case SNDRV_PCM_FORMAT_U24_3LE:
418 return 0x0000800000800000ULL;
419 case SNDRV_PCM_FORMAT_U24_3BE:
420 return 0x0080000080000080ULL;
421 case SNDRV_PCM_FORMAT_U20_3LE:
422 return 0x0000080000080000ULL;
423 case SNDRV_PCM_FORMAT_U20_3BE:
424 return 0x0008000008000008ULL;
425 case SNDRV_PCM_FORMAT_U18_3LE:
426 return 0x0000020000020000ULL;
427 case SNDRV_PCM_FORMAT_U18_3BE:
428 return 0x0002000002000002ULL;
430 case SNDRV_PCM_FORMAT_U16_LE:
431 return 0x0080008000800080ULL;
432 case SNDRV_PCM_FORMAT_U24_LE:
433 return 0x0000800000008000ULL;
434 case SNDRV_PCM_FORMAT_U32_LE:
435 return 0x0000008000000080ULL;
436 case SNDRV_PCM_FORMAT_U16_BE:
437 return 0x8000800080008000ULL;
438 case SNDRV_PCM_FORMAT_U24_BE:
439 return 0x0080000000800000ULL;
440 case SNDRV_PCM_FORMAT_U32_BE:
441 return 0x8000000080000000ULL;
442 case SNDRV_PCM_FORMAT_U24_3LE:
443 return 0x0080000080000080ULL;
444 case SNDRV_PCM_FORMAT_U24_3BE:
445 return 0x0000800000800000ULL;
446 case SNDRV_PCM_FORMAT_U20_3LE:
447 return 0x0008000008000008ULL;
448 case SNDRV_PCM_FORMAT_U20_3BE:
449 return 0x0000080000080000ULL;
450 case SNDRV_PCM_FORMAT_U18_3LE:
451 return 0x0002000002000002ULL;
452 case SNDRV_PCM_FORMAT_U18_3BE:
453 return 0x0000020000020000ULL;
455 case SNDRV_PCM_FORMAT_FLOAT_LE:
461 u.f[0] = u.f[1] = 0.0;
462 #ifdef SNDRV_LITTLE_ENDIAN
465 return bswap_64(u.i);
468 case SNDRV_PCM_FORMAT_FLOAT64_LE:
475 #ifdef SNDRV_LITTLE_ENDIAN
478 return bswap_64(u.i);
481 case SNDRV_PCM_FORMAT_FLOAT_BE:
487 u.f[0] = u.f[1] = 0.0;
488 #ifdef SNDRV_LITTLE_ENDIAN
489 return bswap_64(u.i);
494 case SNDRV_PCM_FORMAT_FLOAT64_BE:
501 #ifdef SNDRV_LITTLE_ENDIAN
502 return bswap_64(u.i);
507 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
508 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
510 case SNDRV_PCM_FORMAT_MU_LAW:
511 return 0x7f7f7f7f7f7f7f7fULL;
512 case SNDRV_PCM_FORMAT_A_LAW:
513 return 0x5555555555555555ULL;
514 case SNDRV_PCM_FORMAT_IMA_ADPCM: /* special case */
515 case SNDRV_PCM_FORMAT_MPEG:
516 case SNDRV_PCM_FORMAT_GSM:
517 case SNDRV_PCM_FORMAT_SPECIAL:
527 * \brief Return 32 bit expressing silence for a PCM sample format
528 * \param format Sample format
529 * \return silence 32 bit word
531 u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
533 assert(snd_pcm_format_physical_width(format) <= 32);
534 return (u_int32_t)snd_pcm_format_silence_64(format);
538 * \brief Return 16 bit expressing silence for a PCM sample format
539 * \param format Sample format
540 * \return silence 16 bit word
542 u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
544 assert(snd_pcm_format_physical_width(format) <= 16);
545 return (u_int16_t)snd_pcm_format_silence_64(format);
549 * \brief Return 8 bit expressing silence for a PCM sample format
550 * \param format Sample format
551 * \return silence 8 bit word
553 u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
555 assert(snd_pcm_format_physical_width(format) <= 8);
556 return (u_int8_t)snd_pcm_format_silence_64(format);
560 * \brief Silence a PCM samples buffer
561 * \param format Sample format
563 * \param samples Samples count
564 * \return 0 if successful or a negative error code
566 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
570 switch (snd_pcm_format_physical_width(format)) {
572 u_int8_t silence = snd_pcm_format_silence_64(format);
573 unsigned int samples1;
574 if (samples % 2 != 0)
576 samples1 = samples / 2;
577 memset(data, silence, samples1);
581 u_int8_t silence = snd_pcm_format_silence_64(format);
582 memset(data, silence, samples);
586 u_int16_t silence = snd_pcm_format_silence_64(format);
587 u_int16_t *pdata = (u_int16_t *)data;
589 memset(data, 0, samples * 2);
591 while (samples-- > 0)
597 u_int32_t silence = snd_pcm_format_silence_64(format);
598 u_int8_t *pdata = (u_int8_t *)data;
600 memset(data, 0, samples * 3);
602 while (samples-- > 0) {
603 #ifdef SNDRV_LITTLE_ENDIAN
604 *pdata++ = silence >> 0;
605 *pdata++ = silence >> 8;
606 *pdata++ = silence >> 16;
608 *pdata++ = silence >> 16;
609 *pdata++ = silence >> 8;
610 *pdata++ = silence >> 0;
617 u_int32_t silence = snd_pcm_format_silence_64(format);
618 u_int32_t *pdata = (u_int32_t *)data;
620 memset(data, 0, samples * 4);
622 while (samples-- > 0)
628 u_int64_t silence = snd_pcm_format_silence_64(format);
629 u_int64_t *pdata = (u_int64_t *)data;
631 memset(data, 0, samples * 8);
633 while (samples-- > 0)
645 static const int linear_formats[4][2][2] = {
646 { { SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8 },
647 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8 } },
648 { { SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE },
649 { SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE } },
650 { { SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE },
651 { SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE } },
652 { { SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE },
653 { SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE } }
656 static const int linear24_formats[3][2][2] = {
657 { { SNDRV_PCM_FORMAT_S24_3LE, SNDRV_PCM_FORMAT_S24_3BE },
658 { SNDRV_PCM_FORMAT_U24_3LE, SNDRV_PCM_FORMAT_U24_3BE } },
659 { { SNDRV_PCM_FORMAT_S20_3LE, SNDRV_PCM_FORMAT_S20_3BE },
660 { SNDRV_PCM_FORMAT_U20_3LE, SNDRV_PCM_FORMAT_U20_3BE } },
661 { { SNDRV_PCM_FORMAT_S18_3LE, SNDRV_PCM_FORMAT_S18_3BE },
662 { SNDRV_PCM_FORMAT_U18_3LE, SNDRV_PCM_FORMAT_U18_3BE } },
666 * \brief Compose a PCM sample linear format
667 * \param width Nominal bits per sample
668 * \param pwidth Physical bit width of the format
669 * \param unsignd Sign: 0 signed, 1 unsigned
670 * \param big_endian Endian: 0 little endian, 1 big endian
671 * \return The matching format type, or #SND_PCM_FORMAT_UNKNOWN if no match
673 snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, int big_endian)
687 return SND_PCM_FORMAT_UNKNOWN;
689 return linear24_formats[width][!!unsignd][!!big_endian];
705 return SND_PCM_FORMAT_UNKNOWN;
707 return linear_formats[width][!!unsignd][!!big_endian];
712 * \brief Parse control element id from the config
713 * \param conf the config tree to parse
714 * \param ctl_id the pointer to store the resultant control element id
715 * \param cardp the pointer to store the card index
716 * \param cchannelsp the pointer to store the number of channels (optional)
717 * \param hwctlp the pointer to store the h/w control flag (optional)
718 * \return 0 if successful, or a negative error code
720 * This function parses the given config tree to retrieve the control element id
721 * and the card index. It's used by softvol. External PCM plugins can use this
722 * function for creating or assigining their controls.
724 * cchannelsp and hwctlp arguments are optional. Set NULL if not necessary.
726 int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp,
727 int *cchannelsp, int *hwctlp)
729 snd_config_iterator_t i, next;
730 int iface = SND_CTL_ELEM_IFACE_MIXER;
731 const char *name = NULL;
737 assert(ctl_id && cardp);
742 snd_config_for_each(i, next, conf) {
743 snd_config_t *n = snd_config_iterator_entry(i);
745 if (snd_config_get_id(n, &id) < 0)
747 if (strcmp(id, "comment") == 0)
749 if (strcmp(id, "card") == 0) {
752 if ((err = snd_config_get_integer(n, &v)) < 0) {
753 if ((err = snd_config_get_string(n, &str)) < 0) {
754 SNDERR("Invalid field %s", id);
757 *cardp = snd_card_get_index(str);
759 SNDERR("Cannot get index for %s", str);
767 if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
769 if ((err = snd_config_get_string(n, &ptr)) < 0) {
770 SNDERR("field %s is not a string", id);
773 if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) {
774 SNDERR("Invalid value for '%s'", id);
780 if (strcmp(id, "name") == 0) {
781 if ((err = snd_config_get_string(n, &name)) < 0) {
782 SNDERR("field %s is not a string", id);
787 if (strcmp(id, "index") == 0) {
788 if ((err = snd_config_get_integer(n, &index)) < 0) {
789 SNDERR("field %s is not an integer", id);
794 if (strcmp(id, "device") == 0) {
795 if ((err = snd_config_get_integer(n, &device)) < 0) {
796 SNDERR("field %s is not an integer", id);
801 if (strcmp(id, "subdevice") == 0) {
802 if ((err = snd_config_get_integer(n, &subdevice)) < 0) {
803 SNDERR("field %s is not an integer", id);
808 if (cchannelsp && strcmp(id, "count") == 0) {
810 if ((err = snd_config_get_integer(n, &v)) < 0) {
811 SNDERR("field %s is not an integer", id);
814 if (v < 1 || v > 2) {
815 SNDERR("Invalid count %ld", v);
821 if (hwctlp && strcmp(id, "hwctl") == 0) {
822 if ((err = snd_config_get_bool(n)) < 0) {
823 SNDERR("The field %s must be a boolean type", id);
829 SNDERR("Unknown field %s", id);
833 SNDERR("Missing control name");
842 snd_ctl_elem_id_set_interface(ctl_id, iface);
843 snd_ctl_elem_id_set_name(ctl_id, name);
844 snd_ctl_elem_id_set_index(ctl_id, index);
845 snd_ctl_elem_id_set_device(ctl_id, device);
846 snd_ctl_elem_id_set_subdevice(ctl_id, subdevice);