OSDN Git Service

Removed duplicated #include
[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 #ifdef __KERNEL__
23 #include "../include/driver.h"
24 #include "../include/pcm.h"
25 #include "../include/pcm_plugin.h"
26 #else
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <byteswap.h>
33 #include "pcm_local.h"
34 #endif
35
36 int snd_pcm_format_signed(int format)
37 {
38         switch (format) {
39         case SND_PCM_SFMT_S8:
40         case SND_PCM_SFMT_S16_LE:
41         case SND_PCM_SFMT_S16_BE:
42         case SND_PCM_SFMT_S24_LE:
43         case SND_PCM_SFMT_S24_BE:
44         case SND_PCM_SFMT_S32_LE:
45         case SND_PCM_SFMT_S32_BE:
46                 return 1;
47         case SND_PCM_SFMT_U8:
48         case SND_PCM_SFMT_U16_LE:
49         case SND_PCM_SFMT_U16_BE:
50         case SND_PCM_SFMT_U24_LE:
51         case SND_PCM_SFMT_U24_BE:
52         case SND_PCM_SFMT_U32_LE:
53         case SND_PCM_SFMT_U32_BE:
54                 return 0;
55         default:
56                 return -EINVAL;
57         }
58 }
59
60 int snd_pcm_format_unsigned(int format)
61 {
62         int val;
63
64         val = snd_pcm_format_signed(format);
65         if (val >= 0)
66                 val ^= 1;
67         return val;
68 }
69
70 int snd_pcm_format_linear(int format)
71 {
72         return snd_pcm_format_signed(format) >= 0;
73 }
74
75 int snd_pcm_format_little_endian(int format)
76 {
77         switch (format) {
78         case SND_PCM_SFMT_S16_LE:
79         case SND_PCM_SFMT_U16_LE:
80         case SND_PCM_SFMT_S24_LE:
81         case SND_PCM_SFMT_U24_LE:
82         case SND_PCM_SFMT_S32_LE:
83         case SND_PCM_SFMT_U32_LE:
84         case SND_PCM_SFMT_FLOAT_LE:
85         case SND_PCM_SFMT_FLOAT64_LE:
86         case SND_PCM_SFMT_IEC958_SUBFRAME_LE:
87                 return 1;
88         case SND_PCM_SFMT_S16_BE:
89         case SND_PCM_SFMT_U16_BE:
90         case SND_PCM_SFMT_S24_BE:
91         case SND_PCM_SFMT_U24_BE:
92         case SND_PCM_SFMT_S32_BE:
93         case SND_PCM_SFMT_U32_BE:
94         case SND_PCM_SFMT_FLOAT_BE:
95         case SND_PCM_SFMT_FLOAT64_BE:
96         case SND_PCM_SFMT_IEC958_SUBFRAME_BE:
97                 return 0;
98         default:
99                 return -EINVAL;
100         }
101 }
102
103 int snd_pcm_format_big_endian(int format)
104 {
105         int val;
106
107         val = snd_pcm_format_little_endian(format);
108         if (val < 0)
109                 return val;
110         return !val;
111 }
112
113 int snd_pcm_format_width(int format)
114 {
115         switch (format) {
116         case SND_PCM_SFMT_S8:
117         case SND_PCM_SFMT_U8:
118                 return 8;
119         case SND_PCM_SFMT_S16_LE:
120         case SND_PCM_SFMT_S16_BE:
121         case SND_PCM_SFMT_U16_LE:
122         case SND_PCM_SFMT_U16_BE:
123                 return 16;
124         case SND_PCM_SFMT_S24_LE:
125         case SND_PCM_SFMT_S24_BE:
126         case SND_PCM_SFMT_U24_LE:
127         case SND_PCM_SFMT_U24_BE:
128                 return 24;
129         case SND_PCM_SFMT_S32_LE:
130         case SND_PCM_SFMT_S32_BE:
131         case SND_PCM_SFMT_U32_LE:
132         case SND_PCM_SFMT_U32_BE:
133         case SND_PCM_SFMT_FLOAT_LE:
134         case SND_PCM_SFMT_FLOAT_BE:
135                 return 32;
136         case SND_PCM_SFMT_FLOAT64_LE:
137         case SND_PCM_SFMT_FLOAT64_BE:
138                 return 64;
139         case SND_PCM_SFMT_IEC958_SUBFRAME_LE:
140         case SND_PCM_SFMT_IEC958_SUBFRAME_BE:
141                 return 24;
142         case SND_PCM_SFMT_MU_LAW:
143         case SND_PCM_SFMT_A_LAW:
144                 return 8;
145         case SND_PCM_SFMT_IMA_ADPCM:
146                 return 4;
147         default:
148                 return -EINVAL;
149         }
150 }
151
152 int snd_pcm_format_physical_width(int format)
153 {
154         switch (format) {
155         case SND_PCM_SFMT_S8:
156         case SND_PCM_SFMT_U8:
157                 return 8;
158         case SND_PCM_SFMT_S16_LE:
159         case SND_PCM_SFMT_S16_BE:
160         case SND_PCM_SFMT_U16_LE:
161         case SND_PCM_SFMT_U16_BE:
162                 return 16;
163         case SND_PCM_SFMT_S24_LE:
164         case SND_PCM_SFMT_S24_BE:
165         case SND_PCM_SFMT_U24_LE:
166         case SND_PCM_SFMT_U24_BE:
167         case SND_PCM_SFMT_S32_LE:
168         case SND_PCM_SFMT_S32_BE:
169         case SND_PCM_SFMT_U32_LE:
170         case SND_PCM_SFMT_U32_BE:
171         case SND_PCM_SFMT_FLOAT_LE:
172         case SND_PCM_SFMT_FLOAT_BE:
173         case SND_PCM_SFMT_IEC958_SUBFRAME_LE:
174         case SND_PCM_SFMT_IEC958_SUBFRAME_BE:
175                 return 32;
176         case SND_PCM_SFMT_FLOAT64_LE:
177         case SND_PCM_SFMT_FLOAT64_BE:
178                 return 64;
179         case SND_PCM_SFMT_MU_LAW:
180         case SND_PCM_SFMT_A_LAW:
181                 return 8;
182         case SND_PCM_SFMT_IMA_ADPCM:
183                 return 4;
184         default:
185                 return -EINVAL;
186         }
187 }
188
189 ssize_t snd_pcm_format_size(int format, size_t samples)
190 {
191         switch (format) {
192         case SND_PCM_SFMT_S8:
193         case SND_PCM_SFMT_U8:
194                 return samples;
195         case SND_PCM_SFMT_S16_LE:
196         case SND_PCM_SFMT_S16_BE:
197         case SND_PCM_SFMT_U16_LE:
198         case SND_PCM_SFMT_U16_BE:
199                 return samples * 2;
200         case SND_PCM_SFMT_S24_LE:
201         case SND_PCM_SFMT_S24_BE:
202         case SND_PCM_SFMT_U24_LE:
203         case SND_PCM_SFMT_U24_BE:
204         case SND_PCM_SFMT_S32_LE:
205         case SND_PCM_SFMT_S32_BE:
206         case SND_PCM_SFMT_U32_LE:
207         case SND_PCM_SFMT_U32_BE:
208         case SND_PCM_SFMT_FLOAT_LE:
209         case SND_PCM_SFMT_FLOAT_BE:
210                 return samples * 4;
211         case SND_PCM_SFMT_FLOAT64_LE:
212         case SND_PCM_SFMT_FLOAT64_BE:
213                 return samples * 8;
214         case SND_PCM_SFMT_IEC958_SUBFRAME_LE:
215         case SND_PCM_SFMT_IEC958_SUBFRAME_BE:
216                 return samples * 4;
217         case SND_PCM_SFMT_MU_LAW:
218         case SND_PCM_SFMT_A_LAW:
219                 return samples;
220         case SND_PCM_SFMT_IMA_ADPCM:
221                 if (samples & 1)
222                         return -EINVAL;
223                 return samples / 2;
224         default:
225                 return -EINVAL;
226         }
227 }
228
229 ssize_t snd_pcm_format_bytes_per_second(snd_pcm_format_t *format)
230 {
231         return snd_pcm_format_size(format->format, format->channels * format->rate);
232 }
233
234 u_int64_t snd_pcm_format_silence_64(int format)
235 {
236         switch (format) {
237         case SND_PCM_SFMT_S8:
238         case SND_PCM_SFMT_S16_LE:
239         case SND_PCM_SFMT_S16_BE:
240         case SND_PCM_SFMT_S24_LE:
241         case SND_PCM_SFMT_S24_BE:
242         case SND_PCM_SFMT_S32_LE:
243         case SND_PCM_SFMT_S32_BE:
244                 return 0;
245         case SND_PCM_SFMT_U8:
246                 return 0x8080808080808080UL;
247         case SND_PCM_SFMT_U16_LE:
248         case SND_PCM_SFMT_U24_LE:
249         case SND_PCM_SFMT_U32_LE:
250 #ifdef SND_LITTLE_ENDIAN
251                 return 0x8000800080008000UL;
252 #else
253                 return 0x0080008000800080UL;
254 #endif
255         case SND_PCM_SFMT_U16_BE:
256         case SND_PCM_SFMT_U24_BE:
257         case SND_PCM_SFMT_U32_BE:
258 #ifdef SND_LITTLE_ENDIAN
259                 return 0x0000008000000080UL;
260 #else
261                 return 0x8000000080000000UL;
262 #endif
263         case SND_PCM_SFMT_FLOAT_LE:             
264 #ifdef SND_LITTLE_ENDIAN
265                 return (float)0.0;
266 #else
267                 return bswap_32((u_int32_t)((float)0.0));
268 #endif
269         case SND_PCM_SFMT_FLOAT64_LE:
270 #ifdef SND_LITTLE_ENDIAN
271                 return (double)0.0;
272 #else
273                 return bswap_64((u_int64_t)((double)0.0));
274 #endif
275         case SND_PCM_SFMT_FLOAT_BE:             
276 #ifdef SND_LITTLE_ENDIAN
277                 return bswap_32((u_int32_t)((float)0.0));
278 #else
279                 return (float)0.0;
280 #endif
281         case SND_PCM_SFMT_FLOAT64_BE:
282 #ifdef SND_LITTLE_ENDIAN
283                 return bswap_64((u_int64_t)((double)0.0));
284 #else
285                 return (double)0.0;
286 #endif
287         case SND_PCM_SFMT_IEC958_SUBFRAME_LE:
288         case SND_PCM_SFMT_IEC958_SUBFRAME_BE:
289                 return 0;       
290         case SND_PCM_SFMT_MU_LAW:
291                 return 0x7f7f7f7f7f7f7f7fUL;
292         case SND_PCM_SFMT_A_LAW:
293                 return 0x5555555555555555UL;
294         case SND_PCM_SFMT_IMA_ADPCM:    /* special case */
295         case SND_PCM_SFMT_MPEG:
296         case SND_PCM_SFMT_GSM:
297                 return 0;
298         }
299         return 0;
300 }
301
302 u_int32_t snd_pcm_format_silence_32(int format)
303 {
304         return (u_int32_t)snd_pcm_format_silence_64(format);
305 }
306
307 u_int16_t snd_pcm_format_silence_16(int format)
308 {
309         return (u_int16_t)snd_pcm_format_silence_64(format);
310 }
311
312 u_int8_t snd_pcm_format_silence(int format)
313 {
314         return (u_int8_t)snd_pcm_format_silence_64(format);
315 }
316
317 ssize_t snd_pcm_format_set_silence(int format, void *data, size_t count)
318 {
319         size_t count1;
320         
321         if (count == 0)
322                 return 0;
323         switch (snd_pcm_format_width(format)) {
324         case 4:
325         case 8: {
326                 u_int8_t silence = snd_pcm_format_silence_64(format);
327                 memset(data, silence, count);
328                 break;
329         }
330         case 16: {
331                 u_int16_t silence = snd_pcm_format_silence_64(format);
332                 if (count % 2)
333                         return -EINVAL;
334                 count1 = count / 2;
335                 while (count1-- > 0)
336                         *((u_int16_t *)data)++ = silence;
337                 break;
338         }
339         case 32: {
340                 u_int32_t silence = snd_pcm_format_silence_64(format);
341                 if (count % 4)
342                         return -EINVAL;
343                 count1 = count / 4;
344                 while (count1-- > 0)
345                         *((u_int32_t *)data)++ = silence;
346                 break;
347         }
348         case 64: {
349                 u_int64_t silence = snd_pcm_format_silence_64(format);
350                 if (count % 8)
351                         return -EINVAL;
352                 count1 = count / 8;
353                 while (count1-- > 0)
354                         *((u_int64_t *)data)++ = silence;
355         }
356         default:
357                 return -EINVAL;
358         }
359         return count;
360 }
361
362 static int linear_formats[4*2*2] = {
363         SND_PCM_SFMT_S8,
364         SND_PCM_SFMT_U8,
365         SND_PCM_SFMT_S8,
366         SND_PCM_SFMT_U8,
367         SND_PCM_SFMT_S16_LE,
368         SND_PCM_SFMT_S16_BE,
369         SND_PCM_SFMT_U16_LE,
370         SND_PCM_SFMT_U16_BE,
371         SND_PCM_SFMT_S24_LE,
372         SND_PCM_SFMT_S24_BE,
373         SND_PCM_SFMT_U24_LE,
374         SND_PCM_SFMT_U24_BE,
375         SND_PCM_SFMT_S32_LE,
376         SND_PCM_SFMT_S32_BE,
377         SND_PCM_SFMT_U32_LE,
378         SND_PCM_SFMT_U32_BE
379 };
380
381 int snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
382 {
383         switch (width) {
384         case 8:
385                 width = 0;
386                 break;
387         case 16:
388                 width = 1;
389                 break;
390         case 24:
391                 width = 2;
392                 break;
393         case 32:
394                 width = 3;
395                 break;
396         default:
397                 return -1;
398         }
399         return ((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian];
400 }