OSDN Git Service

Fixed silence for 24-bit format
[android-x86/external-alsa-lib.git] / src / pcm / pcm_misc.c
1 /*
2  *  PCM Interface - misc routines
3  *  Copyright (c) 1998 by Jaroslav Kysela <perex@suse.cz>
4  *
5  *
6  *   This library is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU Library General Public License as
8  *   published by the Free Software Foundation; either version 2 of
9  *   the License, or (at your option) any later version.
10  *
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 Library General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Library General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21   
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <byteswap.h>
27 #include "pcm_local.h"
28
29
30 /**
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
34  */
35 int snd_pcm_format_signed(snd_pcm_format_t format)
36 {
37         switch (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                 return 1;
46         case SNDRV_PCM_FORMAT_U8:
47         case SNDRV_PCM_FORMAT_U16_LE:
48         case SNDRV_PCM_FORMAT_U16_BE:
49         case SNDRV_PCM_FORMAT_U24_LE:
50         case SNDRV_PCM_FORMAT_U24_BE:
51         case SNDRV_PCM_FORMAT_U32_LE:
52         case SNDRV_PCM_FORMAT_U32_BE:
53                 return 0;
54         default:
55                 return -EINVAL;
56         }
57 }
58
59 /**
60  * \brief Return sign info for a PCM sample linear format
61  * \param format Format
62  * \return 0 signed, 1 unsigned, a negative error code if format is not linear
63  */
64 int snd_pcm_format_unsigned(snd_pcm_format_t format)
65 {
66         int val;
67
68         val = snd_pcm_format_signed(format);
69         if (val < 0)
70                 return val;
71         return !val;
72 }
73
74 /**
75  * \brief Return linear info for a PCM sample format
76  * \param format Format
77  * \return 0 non linear, 1 linear
78  */
79 int snd_pcm_format_linear(snd_pcm_format_t format)
80 {
81         return snd_pcm_format_signed(format) >= 0;
82 }
83
84 /**
85  * \brief Return endian info for a PCM sample format
86  * \param format Format
87  * \return 0 big endian, 1 little endian, a negative error code if endian independent
88  */
89 int snd_pcm_format_little_endian(snd_pcm_format_t format)
90 {
91         switch (format) {
92         case SNDRV_PCM_FORMAT_S16_LE:
93         case SNDRV_PCM_FORMAT_U16_LE:
94         case SNDRV_PCM_FORMAT_S24_LE:
95         case SNDRV_PCM_FORMAT_U24_LE:
96         case SNDRV_PCM_FORMAT_S32_LE:
97         case SNDRV_PCM_FORMAT_U32_LE:
98         case SNDRV_PCM_FORMAT_FLOAT_LE:
99         case SNDRV_PCM_FORMAT_FLOAT64_LE:
100         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
101                 return 1;
102         case SNDRV_PCM_FORMAT_S16_BE:
103         case SNDRV_PCM_FORMAT_U16_BE:
104         case SNDRV_PCM_FORMAT_S24_BE:
105         case SNDRV_PCM_FORMAT_U24_BE:
106         case SNDRV_PCM_FORMAT_S32_BE:
107         case SNDRV_PCM_FORMAT_U32_BE:
108         case SNDRV_PCM_FORMAT_FLOAT_BE:
109         case SNDRV_PCM_FORMAT_FLOAT64_BE:
110         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
111                 return 0;
112         default:
113                 return -EINVAL;
114         }
115 }
116
117 /**
118  * \brief Return endian info for a PCM sample format
119  * \param format Format
120  * \return 0 little endian, 1 big endian, a negative error code if endian independent
121  */
122 int snd_pcm_format_big_endian(snd_pcm_format_t format)
123 {
124         int val;
125
126         val = snd_pcm_format_little_endian(format);
127         if (val < 0)
128                 return val;
129         return !val;
130 }
131
132 /**
133  * \brief Return endian info for a PCM sample format
134  * \param format Format
135  * \return 0 swapped, 1 CPU endian, a negative error code if endian independent
136  */
137 int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
138 {
139 #ifdef SNDRV_LITTLE_ENDIAN
140         return snd_pcm_format_little_endian(format);
141 #else
142         return snd_pcm_format_big_endian(format);
143 #endif
144 }
145
146 /**
147  * \brief Return nominal bits per a PCM sample
148  * \param format Sample format
149  * \return bits per sample, a negative error code if not applicable
150  */
151 int snd_pcm_format_width(snd_pcm_format_t format)
152 {
153         switch (format) {
154         case SNDRV_PCM_FORMAT_S8:
155         case SNDRV_PCM_FORMAT_U8:
156                 return 8;
157         case SNDRV_PCM_FORMAT_S16_LE:
158         case SNDRV_PCM_FORMAT_S16_BE:
159         case SNDRV_PCM_FORMAT_U16_LE:
160         case SNDRV_PCM_FORMAT_U16_BE:
161                 return 16;
162         case SNDRV_PCM_FORMAT_S24_LE:
163         case SNDRV_PCM_FORMAT_S24_BE:
164         case SNDRV_PCM_FORMAT_U24_LE:
165         case SNDRV_PCM_FORMAT_U24_BE:
166                 return 24;
167         case SNDRV_PCM_FORMAT_S32_LE:
168         case SNDRV_PCM_FORMAT_S32_BE:
169         case SNDRV_PCM_FORMAT_U32_LE:
170         case SNDRV_PCM_FORMAT_U32_BE:
171         case SNDRV_PCM_FORMAT_FLOAT_LE:
172         case SNDRV_PCM_FORMAT_FLOAT_BE:
173                 return 32;
174         case SNDRV_PCM_FORMAT_FLOAT64_LE:
175         case SNDRV_PCM_FORMAT_FLOAT64_BE:
176                 return 64;
177         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
178         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
179                 return 24;
180         case SNDRV_PCM_FORMAT_MU_LAW:
181         case SNDRV_PCM_FORMAT_A_LAW:
182                 return 8;
183         case SNDRV_PCM_FORMAT_IMA_ADPCM:
184                 return 4;
185         default:
186                 return -EINVAL;
187         }
188 }
189
190 /**
191  * \brief Return bits needed to store a PCM sample
192  * \param format Sample format
193  * \return bits per sample, a negative error code if not applicable
194  */
195 int snd_pcm_format_physical_width(snd_pcm_format_t format)
196 {
197         switch (format) {
198         case SNDRV_PCM_FORMAT_S8:
199         case SNDRV_PCM_FORMAT_U8:
200                 return 8;
201         case SNDRV_PCM_FORMAT_S16_LE:
202         case SNDRV_PCM_FORMAT_S16_BE:
203         case SNDRV_PCM_FORMAT_U16_LE:
204         case SNDRV_PCM_FORMAT_U16_BE:
205                 return 16;
206         case SNDRV_PCM_FORMAT_S24_LE:
207         case SNDRV_PCM_FORMAT_S24_BE:
208         case SNDRV_PCM_FORMAT_U24_LE:
209         case SNDRV_PCM_FORMAT_U24_BE:
210         case SNDRV_PCM_FORMAT_S32_LE:
211         case SNDRV_PCM_FORMAT_S32_BE:
212         case SNDRV_PCM_FORMAT_U32_LE:
213         case SNDRV_PCM_FORMAT_U32_BE:
214         case SNDRV_PCM_FORMAT_FLOAT_LE:
215         case SNDRV_PCM_FORMAT_FLOAT_BE:
216         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
217         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
218                 return 32;
219         case SNDRV_PCM_FORMAT_FLOAT64_LE:
220         case SNDRV_PCM_FORMAT_FLOAT64_BE:
221                 return 64;
222         case SNDRV_PCM_FORMAT_MU_LAW:
223         case SNDRV_PCM_FORMAT_A_LAW:
224                 return 8;
225         case SNDRV_PCM_FORMAT_IMA_ADPCM:
226                 return 4;
227         default:
228                 return -EINVAL;
229         }
230 }
231
232 /**
233  * \brief Return bytes needed to store a quantity of PCM sample
234  * \param format Sample format
235  * \param samples Samples count
236  * \return bytes needed, a negative error code if not integer or unknown
237  */
238 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
239 {
240         switch (format) {
241         case SNDRV_PCM_FORMAT_S8:
242         case SNDRV_PCM_FORMAT_U8:
243                 return samples;
244         case SNDRV_PCM_FORMAT_S16_LE:
245         case SNDRV_PCM_FORMAT_S16_BE:
246         case SNDRV_PCM_FORMAT_U16_LE:
247         case SNDRV_PCM_FORMAT_U16_BE:
248                 return samples * 2;
249         case SNDRV_PCM_FORMAT_S24_LE:
250         case SNDRV_PCM_FORMAT_S24_BE:
251         case SNDRV_PCM_FORMAT_U24_LE:
252         case SNDRV_PCM_FORMAT_U24_BE:
253         case SNDRV_PCM_FORMAT_S32_LE:
254         case SNDRV_PCM_FORMAT_S32_BE:
255         case SNDRV_PCM_FORMAT_U32_LE:
256         case SNDRV_PCM_FORMAT_U32_BE:
257         case SNDRV_PCM_FORMAT_FLOAT_LE:
258         case SNDRV_PCM_FORMAT_FLOAT_BE:
259                 return samples * 4;
260         case SNDRV_PCM_FORMAT_FLOAT64_LE:
261         case SNDRV_PCM_FORMAT_FLOAT64_BE:
262                 return samples * 8;
263         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
264         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
265                 return samples * 4;
266         case SNDRV_PCM_FORMAT_MU_LAW:
267         case SNDRV_PCM_FORMAT_A_LAW:
268                 return samples;
269         case SNDRV_PCM_FORMAT_IMA_ADPCM:
270                 if (samples & 1)
271                         return -EINVAL;
272                 return samples / 2;
273         default:
274                 assert(0);
275                 return -EINVAL;
276         }
277 }
278
279 /**
280  * \brief Return 64 bit expressing silence for a PCM sample format
281  * \param format Sample format
282  * \return silence 64 bit word
283  */
284 u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
285 {
286         switch (format) {
287         case SNDRV_PCM_FORMAT_S8:
288         case SNDRV_PCM_FORMAT_S16_LE:
289         case SNDRV_PCM_FORMAT_S16_BE:
290         case SNDRV_PCM_FORMAT_S24_LE:
291         case SNDRV_PCM_FORMAT_S24_BE:
292         case SNDRV_PCM_FORMAT_S32_LE:
293         case SNDRV_PCM_FORMAT_S32_BE:
294                 return 0;
295         case SNDRV_PCM_FORMAT_U8:
296                 return 0x8080808080808080ULL;
297 #ifdef SNDRV_LITTLE_ENDIAN
298         case SNDRV_PCM_FORMAT_U16_LE:
299                 return 0x8000800080008000ULL;
300         case SNDRV_PCM_FORMAT_U24_LE:
301                 return 0x0080000000800000ULL;
302         case SNDRV_PCM_FORMAT_U32_LE:
303                 return 0x8000000080000000ULL;
304         case SNDRV_PCM_FORMAT_U16_BE:
305                 return 0x0080008000800080ULL;
306         case SNDRV_PCM_FORMAT_U24_BE:
307                 return 0x0000800000008000ULL;
308         case SNDRV_PCM_FORMAT_U32_BE:
309                 return 0x0000008000000080ULL;
310 #else
311         case SNDRV_PCM_FORMAT_U16_LE:
312                 return 0x0080008000800080ULL;
313         case SNDRV_PCM_FORMAT_U24_LE:
314                 return 0x0000800000008000ULL;
315         case SNDRV_PCM_FORMAT_U32_LE:
316                 return 0x0000008000000080ULL;
317         case SNDRV_PCM_FORMAT_U16_BE:
318                 return 0x8000800080008000ULL;
319         case SNDRV_PCM_FORMAT_U24_BE:
320                 return 0x0080000000800000ULL;
321         case SNDRV_PCM_FORMAT_U32_BE:
322                 return 0x8000000080000000ULL;
323 #endif
324         case SNDRV_PCM_FORMAT_FLOAT_LE:
325         {
326                 union {
327                         float f;
328                         u_int32_t i;
329                 } u;
330                 u.f = 0.0;
331 #ifdef SNDRV_LITTLE_ENDIAN
332                 return u.i;
333 #else
334                 return bswap_32(u.i);
335 #endif
336         }
337         case SNDRV_PCM_FORMAT_FLOAT64_LE:
338         {
339                 union {
340                         double f;
341                         u_int64_t i;
342                 } u;
343                 u.f = 0.0;
344 #ifdef SNDRV_LITTLE_ENDIAN
345                 return u.i;
346 #else
347                 return bswap_64(u.i);
348 #endif
349         }
350         case SNDRV_PCM_FORMAT_FLOAT_BE:         
351         {
352                 union {
353                         float f;
354                         u_int32_t i;
355                 } u;
356                 u.f = 0.0;
357 #ifdef SNDRV_LITTLE_ENDIAN
358                 return bswap_32(u.i);
359 #else
360                 return u.i;
361 #endif
362         }
363         case SNDRV_PCM_FORMAT_FLOAT64_BE:
364         {
365                 union {
366                         double f;
367                         u_int64_t i;
368                 } u;
369                 u.f = 0.0;
370 #ifdef SNDRV_LITTLE_ENDIAN
371                 return bswap_64(u.i);
372 #else
373                 return u.i;
374 #endif
375         }
376         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
377         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
378                 return 0;       
379         case SNDRV_PCM_FORMAT_MU_LAW:
380                 return 0x7f7f7f7f7f7f7f7fULL;
381         case SNDRV_PCM_FORMAT_A_LAW:
382                 return 0x5555555555555555ULL;
383         case SNDRV_PCM_FORMAT_IMA_ADPCM:        /* special case */
384         case SNDRV_PCM_FORMAT_MPEG:
385         case SNDRV_PCM_FORMAT_GSM:
386         case SNDRV_PCM_FORMAT_SPECIAL:
387                 return 0;
388         default:
389                 assert(0);
390                 return 0;
391         }
392         return 0;
393 }
394
395 /**
396  * \brief Return 32 bit expressing silence for a PCM sample format
397  * \param format Sample format
398  * \return silence 32 bit word
399  */
400 u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
401 {
402         assert(snd_pcm_format_physical_width(format) <= 32);
403         return (u_int32_t)snd_pcm_format_silence_64(format);
404 }
405
406 /**
407  * \brief Return 16 bit expressing silence for a PCM sample format
408  * \param format Sample format
409  * \return silence 16 bit word
410  */
411 u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
412 {
413         assert(snd_pcm_format_physical_width(format) <= 16);
414         return (u_int16_t)snd_pcm_format_silence_64(format);
415 }
416
417 /**
418  * \brief Return 8 bit expressing silence for a PCM sample format
419  * \param format Sample format
420  * \return silence 8 bit word
421  */
422 u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
423 {
424         assert(snd_pcm_format_physical_width(format) <= 8);
425         return (u_int8_t)snd_pcm_format_silence_64(format);
426 }
427
428 /**
429  * \brief Silence a PCM samples buufer
430  * \param format Sample format
431  * \param data Buffer
432  * \return samples Samples count
433  */
434 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
435 {
436         if (samples == 0)
437                 return 0;
438         switch (snd_pcm_format_physical_width(format)) {
439         case 4: {
440                 u_int8_t silence = snd_pcm_format_silence_64(format);
441                 unsigned int samples1;
442                 if (samples % 2 != 0)
443                         return -EINVAL;
444                 samples1 = samples / 2;
445                 memset(data, silence, samples1);
446                 break;
447         }
448         case 8: {
449                 u_int8_t silence = snd_pcm_format_silence_64(format);
450                 memset(data, silence, samples);
451                 break;
452         }
453         case 16: {
454                 u_int16_t silence = snd_pcm_format_silence_64(format);
455                 while (samples-- > 0)
456                         *((u_int16_t *)data)++ = silence;
457                 break;
458         }
459         case 32: {
460                 u_int32_t silence = snd_pcm_format_silence_64(format);
461                 while (samples-- > 0)
462                         *((u_int32_t *)data)++ = silence;
463                 break;
464         }
465         case 64: {
466                 u_int64_t silence = snd_pcm_format_silence_64(format);
467                 while (samples-- > 0)
468                         *((u_int64_t *)data)++ = silence;
469                 break;
470         }
471         default:
472                 assert(0);
473                 return -EINVAL;
474         }
475         return 0;
476 }
477
478 static int linear_formats[4*2*2] = {
479         SNDRV_PCM_FORMAT_S8,
480         SNDRV_PCM_FORMAT_S8,
481         SNDRV_PCM_FORMAT_U8,
482         SNDRV_PCM_FORMAT_U8,
483         SNDRV_PCM_FORMAT_S16_LE,
484         SNDRV_PCM_FORMAT_S16_BE,
485         SNDRV_PCM_FORMAT_U16_LE,
486         SNDRV_PCM_FORMAT_U16_BE,
487         SNDRV_PCM_FORMAT_S24_LE,
488         SNDRV_PCM_FORMAT_S24_BE,
489         SNDRV_PCM_FORMAT_U24_LE,
490         SNDRV_PCM_FORMAT_U24_BE,
491         SNDRV_PCM_FORMAT_S32_LE,
492         SNDRV_PCM_FORMAT_S32_BE,
493         SNDRV_PCM_FORMAT_U32_LE,
494         SNDRV_PCM_FORMAT_U32_BE
495 };
496
497 /**
498  * \brief Compose a PCM sample linear format
499  * \param width Nominal bits per sample
500  * \param unsignd Sign: 0 signed, 1 unsigned
501  * \return big_endian Endianness: 0 little endian, 1 big endian
502  */
503 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
504 {
505         switch (width) {
506         case 8:
507                 width = 0;
508                 break;
509         case 16:
510                 width = 1;
511                 break;
512         case 24:
513                 width = 2;
514                 break;
515         case 32:
516                 width = 3;
517                 break;
518         default:
519                 return SND_PCM_FORMAT_UNKNOWN;
520         }
521         return ((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian];
522 }