OSDN Git Service

Corrections by Kevin Conder <kconder@interaccess.com>
[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 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.
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 Lesser General Public License for more details.
15  *
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
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 float info for a PCM sample format
86  * \param format Format
87  * \return 0 non float, 1 float
88  */
89 int snd_pcm_format_float(snd_pcm_format_t format)
90 {
91         switch (format) {
92         case SNDRV_PCM_FORMAT_FLOAT_LE:
93         case SNDRV_PCM_FORMAT_FLOAT_BE:
94         case SNDRV_PCM_FORMAT_FLOAT64_LE:
95         case SNDRV_PCM_FORMAT_FLOAT64_BE:
96                 return 1;
97         default:
98                 return 0;
99         }
100 }
101
102 /**
103  * \brief Return endian info for a PCM sample format
104  * \param format Format
105  * \return 0 big endian, 1 little endian, a negative error code if endian independent
106  */
107 int snd_pcm_format_little_endian(snd_pcm_format_t format)
108 {
109         switch (format) {
110         case SNDRV_PCM_FORMAT_S16_LE:
111         case SNDRV_PCM_FORMAT_U16_LE:
112         case SNDRV_PCM_FORMAT_S24_LE:
113         case SNDRV_PCM_FORMAT_U24_LE:
114         case SNDRV_PCM_FORMAT_S32_LE:
115         case SNDRV_PCM_FORMAT_U32_LE:
116         case SNDRV_PCM_FORMAT_FLOAT_LE:
117         case SNDRV_PCM_FORMAT_FLOAT64_LE:
118         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
119                 return 1;
120         case SNDRV_PCM_FORMAT_S16_BE:
121         case SNDRV_PCM_FORMAT_U16_BE:
122         case SNDRV_PCM_FORMAT_S24_BE:
123         case SNDRV_PCM_FORMAT_U24_BE:
124         case SNDRV_PCM_FORMAT_S32_BE:
125         case SNDRV_PCM_FORMAT_U32_BE:
126         case SNDRV_PCM_FORMAT_FLOAT_BE:
127         case SNDRV_PCM_FORMAT_FLOAT64_BE:
128         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
129                 return 0;
130         default:
131                 return -EINVAL;
132         }
133 }
134
135 /**
136  * \brief Return endian info for a PCM sample format
137  * \param format Format
138  * \return 0 little endian, 1 big endian, a negative error code if endian independent
139  */
140 int snd_pcm_format_big_endian(snd_pcm_format_t format)
141 {
142         int val;
143
144         val = snd_pcm_format_little_endian(format);
145         if (val < 0)
146                 return val;
147         return !val;
148 }
149
150 /**
151  * \brief Return endian info for a PCM sample format
152  * \param format Format
153  * \return 0 swapped, 1 CPU endian, a negative error code if endian independent
154  */
155 int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
156 {
157 #ifdef SNDRV_LITTLE_ENDIAN
158         return snd_pcm_format_little_endian(format);
159 #else
160         return snd_pcm_format_big_endian(format);
161 #endif
162 }
163
164 /**
165  * \brief Return nominal bits per a PCM sample
166  * \param format Sample format
167  * \return bits per sample, a negative error code if not applicable
168  */
169 int snd_pcm_format_width(snd_pcm_format_t format)
170 {
171         switch (format) {
172         case SNDRV_PCM_FORMAT_S8:
173         case SNDRV_PCM_FORMAT_U8:
174                 return 8;
175         case SNDRV_PCM_FORMAT_S16_LE:
176         case SNDRV_PCM_FORMAT_S16_BE:
177         case SNDRV_PCM_FORMAT_U16_LE:
178         case SNDRV_PCM_FORMAT_U16_BE:
179                 return 16;
180         case SNDRV_PCM_FORMAT_S24_LE:
181         case SNDRV_PCM_FORMAT_S24_BE:
182         case SNDRV_PCM_FORMAT_U24_LE:
183         case SNDRV_PCM_FORMAT_U24_BE:
184                 return 24;
185         case SNDRV_PCM_FORMAT_S32_LE:
186         case SNDRV_PCM_FORMAT_S32_BE:
187         case SNDRV_PCM_FORMAT_U32_LE:
188         case SNDRV_PCM_FORMAT_U32_BE:
189         case SNDRV_PCM_FORMAT_FLOAT_LE:
190         case SNDRV_PCM_FORMAT_FLOAT_BE:
191                 return 32;
192         case SNDRV_PCM_FORMAT_FLOAT64_LE:
193         case SNDRV_PCM_FORMAT_FLOAT64_BE:
194                 return 64;
195         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
196         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
197                 return 24;
198         case SNDRV_PCM_FORMAT_MU_LAW:
199         case SNDRV_PCM_FORMAT_A_LAW:
200                 return 8;
201         case SNDRV_PCM_FORMAT_IMA_ADPCM:
202                 return 4;
203         default:
204                 return -EINVAL;
205         }
206 }
207
208 /**
209  * \brief Return bits needed to store a PCM sample
210  * \param format Sample format
211  * \return bits per sample, a negative error code if not applicable
212  */
213 int snd_pcm_format_physical_width(snd_pcm_format_t format)
214 {
215         switch (format) {
216         case SNDRV_PCM_FORMAT_S8:
217         case SNDRV_PCM_FORMAT_U8:
218                 return 8;
219         case SNDRV_PCM_FORMAT_S16_LE:
220         case SNDRV_PCM_FORMAT_S16_BE:
221         case SNDRV_PCM_FORMAT_U16_LE:
222         case SNDRV_PCM_FORMAT_U16_BE:
223                 return 16;
224         case SNDRV_PCM_FORMAT_S24_LE:
225         case SNDRV_PCM_FORMAT_S24_BE:
226         case SNDRV_PCM_FORMAT_U24_LE:
227         case SNDRV_PCM_FORMAT_U24_BE:
228         case SNDRV_PCM_FORMAT_S32_LE:
229         case SNDRV_PCM_FORMAT_S32_BE:
230         case SNDRV_PCM_FORMAT_U32_LE:
231         case SNDRV_PCM_FORMAT_U32_BE:
232         case SNDRV_PCM_FORMAT_FLOAT_LE:
233         case SNDRV_PCM_FORMAT_FLOAT_BE:
234         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
235         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
236                 return 32;
237         case SNDRV_PCM_FORMAT_FLOAT64_LE:
238         case SNDRV_PCM_FORMAT_FLOAT64_BE:
239                 return 64;
240         case SNDRV_PCM_FORMAT_MU_LAW:
241         case SNDRV_PCM_FORMAT_A_LAW:
242                 return 8;
243         case SNDRV_PCM_FORMAT_IMA_ADPCM:
244                 return 4;
245         default:
246                 return -EINVAL;
247         }
248 }
249
250 /**
251  * \brief Return bytes needed to store a quantity of PCM sample
252  * \param format Sample format
253  * \param samples Samples count
254  * \return bytes needed, a negative error code if not integer or unknown
255  */
256 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
257 {
258         switch (format) {
259         case SNDRV_PCM_FORMAT_S8:
260         case SNDRV_PCM_FORMAT_U8:
261                 return samples;
262         case SNDRV_PCM_FORMAT_S16_LE:
263         case SNDRV_PCM_FORMAT_S16_BE:
264         case SNDRV_PCM_FORMAT_U16_LE:
265         case SNDRV_PCM_FORMAT_U16_BE:
266                 return samples * 2;
267         case SNDRV_PCM_FORMAT_S24_LE:
268         case SNDRV_PCM_FORMAT_S24_BE:
269         case SNDRV_PCM_FORMAT_U24_LE:
270         case SNDRV_PCM_FORMAT_U24_BE:
271         case SNDRV_PCM_FORMAT_S32_LE:
272         case SNDRV_PCM_FORMAT_S32_BE:
273         case SNDRV_PCM_FORMAT_U32_LE:
274         case SNDRV_PCM_FORMAT_U32_BE:
275         case SNDRV_PCM_FORMAT_FLOAT_LE:
276         case SNDRV_PCM_FORMAT_FLOAT_BE:
277                 return samples * 4;
278         case SNDRV_PCM_FORMAT_FLOAT64_LE:
279         case SNDRV_PCM_FORMAT_FLOAT64_BE:
280                 return samples * 8;
281         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
282         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
283                 return samples * 4;
284         case SNDRV_PCM_FORMAT_MU_LAW:
285         case SNDRV_PCM_FORMAT_A_LAW:
286                 return samples;
287         case SNDRV_PCM_FORMAT_IMA_ADPCM:
288                 if (samples & 1)
289                         return -EINVAL;
290                 return samples / 2;
291         default:
292                 assert(0);
293                 return -EINVAL;
294         }
295 }
296
297 /**
298  * \brief Return 64 bit expressing silence for a PCM sample format
299  * \param format Sample format
300  * \return silence 64 bit word
301  */
302 u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
303 {
304         switch (format) {
305         case SNDRV_PCM_FORMAT_S8:
306         case SNDRV_PCM_FORMAT_S16_LE:
307         case SNDRV_PCM_FORMAT_S16_BE:
308         case SNDRV_PCM_FORMAT_S24_LE:
309         case SNDRV_PCM_FORMAT_S24_BE:
310         case SNDRV_PCM_FORMAT_S32_LE:
311         case SNDRV_PCM_FORMAT_S32_BE:
312                 return 0;
313         case SNDRV_PCM_FORMAT_U8:
314                 return 0x8080808080808080ULL;
315 #ifdef SNDRV_LITTLE_ENDIAN
316         case SNDRV_PCM_FORMAT_U16_LE:
317                 return 0x8000800080008000ULL;
318         case SNDRV_PCM_FORMAT_U24_LE:
319                 return 0x0080000000800000ULL;
320         case SNDRV_PCM_FORMAT_U32_LE:
321                 return 0x8000000080000000ULL;
322         case SNDRV_PCM_FORMAT_U16_BE:
323                 return 0x0080008000800080ULL;
324         case SNDRV_PCM_FORMAT_U24_BE:
325                 return 0x0000800000008000ULL;
326         case SNDRV_PCM_FORMAT_U32_BE:
327                 return 0x0000008000000080ULL;
328 #else
329         case SNDRV_PCM_FORMAT_U16_LE:
330                 return 0x0080008000800080ULL;
331         case SNDRV_PCM_FORMAT_U24_LE:
332                 return 0x0000800000008000ULL;
333         case SNDRV_PCM_FORMAT_U32_LE:
334                 return 0x0000008000000080ULL;
335         case SNDRV_PCM_FORMAT_U16_BE:
336                 return 0x8000800080008000ULL;
337         case SNDRV_PCM_FORMAT_U24_BE:
338                 return 0x0080000000800000ULL;
339         case SNDRV_PCM_FORMAT_U32_BE:
340                 return 0x8000000080000000ULL;
341 #endif
342         case SNDRV_PCM_FORMAT_FLOAT_LE:
343         {
344                 union {
345                         float f;
346                         u_int32_t i;
347                 } u;
348                 u.f = 0.0;
349 #ifdef SNDRV_LITTLE_ENDIAN
350                 return u.i;
351 #else
352                 return bswap_32(u.i);
353 #endif
354         }
355         case SNDRV_PCM_FORMAT_FLOAT64_LE:
356         {
357                 union {
358                         double f;
359                         u_int64_t i;
360                 } u;
361                 u.f = 0.0;
362 #ifdef SNDRV_LITTLE_ENDIAN
363                 return u.i;
364 #else
365                 return bswap_64(u.i);
366 #endif
367         }
368         case SNDRV_PCM_FORMAT_FLOAT_BE:         
369         {
370                 union {
371                         float f;
372                         u_int32_t i;
373                 } u;
374                 u.f = 0.0;
375 #ifdef SNDRV_LITTLE_ENDIAN
376                 return bswap_32(u.i);
377 #else
378                 return u.i;
379 #endif
380         }
381         case SNDRV_PCM_FORMAT_FLOAT64_BE:
382         {
383                 union {
384                         double f;
385                         u_int64_t i;
386                 } u;
387                 u.f = 0.0;
388 #ifdef SNDRV_LITTLE_ENDIAN
389                 return bswap_64(u.i);
390 #else
391                 return u.i;
392 #endif
393         }
394         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
395         case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
396                 return 0;       
397         case SNDRV_PCM_FORMAT_MU_LAW:
398                 return 0x7f7f7f7f7f7f7f7fULL;
399         case SNDRV_PCM_FORMAT_A_LAW:
400                 return 0x5555555555555555ULL;
401         case SNDRV_PCM_FORMAT_IMA_ADPCM:        /* special case */
402         case SNDRV_PCM_FORMAT_MPEG:
403         case SNDRV_PCM_FORMAT_GSM:
404         case SNDRV_PCM_FORMAT_SPECIAL:
405                 return 0;
406         default:
407                 assert(0);
408                 return 0;
409         }
410         return 0;
411 }
412
413 /**
414  * \brief Return 32 bit expressing silence for a PCM sample format
415  * \param format Sample format
416  * \return silence 32 bit word
417  */
418 u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
419 {
420         assert(snd_pcm_format_physical_width(format) <= 32);
421         return (u_int32_t)snd_pcm_format_silence_64(format);
422 }
423
424 /**
425  * \brief Return 16 bit expressing silence for a PCM sample format
426  * \param format Sample format
427  * \return silence 16 bit word
428  */
429 u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
430 {
431         assert(snd_pcm_format_physical_width(format) <= 16);
432         return (u_int16_t)snd_pcm_format_silence_64(format);
433 }
434
435 /**
436  * \brief Return 8 bit expressing silence for a PCM sample format
437  * \param format Sample format
438  * \return silence 8 bit word
439  */
440 u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
441 {
442         assert(snd_pcm_format_physical_width(format) <= 8);
443         return (u_int8_t)snd_pcm_format_silence_64(format);
444 }
445
446 /**
447  * \brief Silence a PCM samples buffer
448  * \param format Sample format
449  * \param data Buffer
450  * \return samples Samples count
451  */
452 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
453 {
454         if (samples == 0)
455                 return 0;
456         switch (snd_pcm_format_physical_width(format)) {
457         case 4: {
458                 u_int8_t silence = snd_pcm_format_silence_64(format);
459                 unsigned int samples1;
460                 if (samples % 2 != 0)
461                         return -EINVAL;
462                 samples1 = samples / 2;
463                 memset(data, silence, samples1);
464                 break;
465         }
466         case 8: {
467                 u_int8_t silence = snd_pcm_format_silence_64(format);
468                 memset(data, silence, samples);
469                 break;
470         }
471         case 16: {
472                 u_int16_t silence = snd_pcm_format_silence_64(format);
473                 while (samples-- > 0)
474                         *((u_int16_t *)data)++ = silence;
475                 break;
476         }
477         case 32: {
478                 u_int32_t silence = snd_pcm_format_silence_64(format);
479                 while (samples-- > 0)
480                         *((u_int32_t *)data)++ = silence;
481                 break;
482         }
483         case 64: {
484                 u_int64_t silence = snd_pcm_format_silence_64(format);
485                 while (samples-- > 0)
486                         *((u_int64_t *)data)++ = silence;
487                 break;
488         }
489         default:
490                 assert(0);
491                 return -EINVAL;
492         }
493         return 0;
494 }
495
496 static int linear_formats[4*2*2] = {
497         SNDRV_PCM_FORMAT_S8,
498         SNDRV_PCM_FORMAT_S8,
499         SNDRV_PCM_FORMAT_U8,
500         SNDRV_PCM_FORMAT_U8,
501         SNDRV_PCM_FORMAT_S16_LE,
502         SNDRV_PCM_FORMAT_S16_BE,
503         SNDRV_PCM_FORMAT_U16_LE,
504         SNDRV_PCM_FORMAT_U16_BE,
505         SNDRV_PCM_FORMAT_S24_LE,
506         SNDRV_PCM_FORMAT_S24_BE,
507         SNDRV_PCM_FORMAT_U24_LE,
508         SNDRV_PCM_FORMAT_U24_BE,
509         SNDRV_PCM_FORMAT_S32_LE,
510         SNDRV_PCM_FORMAT_S32_BE,
511         SNDRV_PCM_FORMAT_U32_LE,
512         SNDRV_PCM_FORMAT_U32_BE
513 };
514
515 /**
516  * \brief Compose a PCM sample linear format
517  * \param width Nominal bits per sample
518  * \param unsignd Sign: 0 signed, 1 unsigned
519  * \return big_endian Endian: 0 little endian, 1 big endian
520  */
521 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
522 {
523         switch (width) {
524         case 8:
525                 width = 0;
526                 break;
527         case 16:
528                 width = 1;
529                 break;
530         case 24:
531                 width = 2;
532                 break;
533         case 32:
534                 width = 3;
535                 break;
536         default:
537                 return SND_PCM_FORMAT_UNKNOWN;
538         }
539         return ((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian];
540 }