pulling trunk
[ardour.git] / libs / libsndfile / src / command.c
1 /*
2 ** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include        "sfconfig.h"
20
21 #include        <stdio.h>
22 #include        <string.h>
23 #include        <math.h>
24
25 #include        "sndfile.h"
26 #include        "common.h"
27
28 static SF_FORMAT_INFO const simple_formats [] =
29 {
30         {       SF_FORMAT_AIFF | SF_FORMAT_PCM_16,
31                 "AIFF (Apple/SGI 16 bit PCM)", "aiff"
32                 },
33
34         {       SF_FORMAT_AIFF | SF_FORMAT_FLOAT,
35                 "AIFF (Apple/SGI 32 bit float)", "aifc"
36                 },
37
38         {       SF_FORMAT_AIFF | SF_FORMAT_PCM_S8,
39                 "AIFF (Apple/SGI 8 bit PCM)", "aiff"
40                 },
41
42         {       SF_FORMAT_AU | SF_FORMAT_PCM_16,
43                 "AU (Sun/Next 16 bit PCM)", "au"
44                 },
45
46         {       SF_FORMAT_AU | SF_FORMAT_ULAW,
47                 "AU (Sun/Next 8-bit u-law)", "au"
48                 },
49
50         {       SF_FORMAT_CAF | SF_FORMAT_PCM_16,
51                 "CAF (Apple 16 bit PCM)", "caf"
52                 },
53
54 #ifdef HAVE_FLAC_ALL_H
55         {       SF_FORMAT_FLAC | SF_FORMAT_PCM_16,
56                 "FLAC 16 bit", "flac"
57                 },
58 #endif
59
60         {       SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
61                 "OKI Dialogic VOX ADPCM", "vox"
62                 },
63
64         {       SF_FORMAT_WAV | SF_FORMAT_PCM_16,
65                 "WAV (Microsoft 16 bit PCM)", "wav"
66                 },
67
68         {       SF_FORMAT_WAV | SF_FORMAT_FLOAT,
69                 "WAV (Microsoft 32 bit float)", "wav"
70                 },
71
72         {       SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM,
73                 "WAV (Microsoft 4 bit IMA ADPCM)", "wav"
74                 },
75
76         {       SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM,
77                 "WAV (Microsoft 4 bit MS ADPCM)", "wav"
78                 },
79
80         {       SF_FORMAT_WAV | SF_FORMAT_PCM_U8,
81                 "WAV (Microsoft 8 bit PCM)", "wav"
82                 },
83
84 } ; /* simple_formats */
85
86 int
87 psf_get_format_simple_count     (void)
88 {       return (sizeof (simple_formats) / sizeof (SF_FORMAT_INFO)) ;
89 } /* psf_get_format_simple_count */
90
91 int
92 psf_get_format_simple (SF_FORMAT_INFO *data)
93 {       int indx ;
94
95         if (data->format < 0 || data->format >= (SIGNED_SIZEOF (simple_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
96                 return SFE_BAD_CONTROL_CMD ;
97
98         indx = data->format ;
99         memcpy (data, &(simple_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
100
101         return 0 ;
102 } /* psf_get_format_simple */
103
104 /*============================================================================
105 ** Major format info.
106 */
107
108 static SF_FORMAT_INFO const major_formats [] =
109 {
110         {       SF_FORMAT_AIFF,         "AIFF (Apple/SGI)",                                             "aiff"  },
111         {       SF_FORMAT_AU,           "AU (Sun/NeXT)",                                                "au"    },
112         {       SF_FORMAT_AVR,          "AVR (Audio Visual Research)",                  "avr"   },
113         {       SF_FORMAT_CAF,          "CAF (Apple Core Audio File)",                  "caf"   },
114 #ifdef HAVE_FLAC_ALL_H
115         {       SF_FORMAT_FLAC,         "FLAC (FLAC Lossless Audio Codec)",             "flac"  },
116 #endif
117         {       SF_FORMAT_HTK,          "HTK (HMM Tool Kit)",                                   "htk"   },
118         {       SF_FORMAT_SVX,          "IFF (Amiga IFF/SVX8/SV16)",                    "iff"   },
119         {       SF_FORMAT_MAT4,         "MAT4 (GNU Octave 2.0 / Matlab 4.2)",   "mat"   },
120         {       SF_FORMAT_MAT5,         "MAT5 (GNU Octave 2.1 / Matlab 5.0)",   "mat"   },
121         {       SF_FORMAT_PAF,          "PAF (Ensoniq PARIS)",                                  "paf"   },
122         {       SF_FORMAT_PVF,          "PVF (Portable Voice Format)",                  "pvf"   },
123         {       SF_FORMAT_RAW,          "RAW (header-less)",                                    "raw"   },
124         {       SF_FORMAT_SD2,          "SD2 (Sound Designer II)",                              "sd2"   },
125         {       SF_FORMAT_SDS,          "SDS (Midi Sample Dump Standard)",              "sds"   },
126         {       SF_FORMAT_IRCAM,        "SF (Berkeley/IRCAM/CARL)",                             "sf"    },
127         {       SF_FORMAT_VOC,          "VOC (Creative Labs)",                                  "voc"   },
128         {       SF_FORMAT_W64,          "W64 (SoundFoundry WAVE 64)",                   "w64"   },
129         {       SF_FORMAT_WAV,          "WAV (Microsoft)",                                              "wav"   },
130         {       SF_FORMAT_NIST,         "WAV (NIST Sphere)",                                    "wav"   },
131         {       SF_FORMAT_WAVEX,        "WAVEX (Microsoft)",                                    "wav"   },
132         {       SF_FORMAT_XI,           "XI (FastTracker 2)",                                   "xi"    },
133
134 } ; /* major_formats */
135
136 int
137 psf_get_format_major_count      (void)
138 {       return (sizeof (major_formats) / sizeof (SF_FORMAT_INFO)) ;
139 } /* psf_get_format_major_count */
140
141 int
142 psf_get_format_major (SF_FORMAT_INFO *data)
143 {       int indx ;
144
145         if (data->format < 0 || data->format >= (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
146                 return SFE_BAD_CONTROL_CMD ;
147
148         indx = data->format ;
149         memcpy (data, &(major_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
150
151         return 0 ;
152 } /* psf_get_format_major */
153
154 /*============================================================================
155 ** Subtype format info.
156 */
157
158 static SF_FORMAT_INFO subtype_formats [] =
159 {
160         {       SF_FORMAT_PCM_S8,               "Signed 8 bit PCM",             NULL    },
161         {       SF_FORMAT_PCM_16,               "Signed 16 bit PCM",    NULL    },
162         {       SF_FORMAT_PCM_24,               "Signed 24 bit PCM",    NULL    },
163         {       SF_FORMAT_PCM_32,               "Signed 32 bit PCM",    NULL    },
164
165         {       SF_FORMAT_PCM_U8,               "Unsigned 8 bit PCM",   NULL    },
166
167         {       SF_FORMAT_FLOAT,                "32 bit float",                 NULL    },
168         {       SF_FORMAT_DOUBLE,               "64 bit float",                 NULL    },
169
170         {       SF_FORMAT_ULAW,                 "U-Law",                                NULL    },
171         {       SF_FORMAT_ALAW,                 "A-Law",                                NULL    },
172         {       SF_FORMAT_IMA_ADPCM,    "IMA ADPCM",                    NULL    },
173         {       SF_FORMAT_MS_ADPCM,             "Microsoft ADPCM",              NULL    },
174
175         {       SF_FORMAT_GSM610,               "GSM 6.10",                             NULL    },
176
177         {       SF_FORMAT_G721_32,              "32kbs G721 ADPCM",             NULL    },
178         {       SF_FORMAT_G723_24,              "24kbs G723 ADPCM",             NULL    },
179
180         {       SF_FORMAT_DWVW_12,              "12 bit DWVW",                  NULL    },
181         {       SF_FORMAT_DWVW_16,              "16 bit DWVW",                  NULL    },
182         {       SF_FORMAT_DWVW_24,              "24 bit DWVW",                  NULL    },
183         {       SF_FORMAT_VOX_ADPCM,    "VOX ADPCM",                    "vox"   },
184
185         {       SF_FORMAT_DPCM_16,              "16 bit DPCM",                  NULL    },
186         {       SF_FORMAT_DPCM_8,               "8 bit DPCM",                   NULL    }
187 } ; /* subtype_formats */
188
189 int
190 psf_get_format_subtype_count    (void)
191 {       return (sizeof (subtype_formats) / sizeof (SF_FORMAT_INFO)) ;
192 } /* psf_get_format_subtype_count */
193
194 int
195 psf_get_format_subtype (SF_FORMAT_INFO *data)
196 {       int indx ;
197
198         if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
199                 return SFE_BAD_CONTROL_CMD ;
200
201         indx = data->format ;
202         memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ;
203
204         return 0 ;
205 } /* psf_get_format_subtype */
206
207 /*==============================================================================
208 */
209
210 int
211 psf_get_format_info (SF_FORMAT_INFO *data)
212 {       int k, format ;
213
214         if (data->format & SF_FORMAT_TYPEMASK)
215         {       format = data->format & SF_FORMAT_TYPEMASK ;
216
217                 for (k = 0 ; k < (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
218                 {       if (format == major_formats [k].format)
219                         {       memcpy (data, &(major_formats [k]), sizeof (SF_FORMAT_INFO)) ;
220                                 return 0 ;
221                                 } ;
222                         } ;
223                 }
224         else if (data->format & SF_FORMAT_SUBMASK)
225         {       format = data->format & SF_FORMAT_SUBMASK ;
226
227                 for (k = 0 ; k < (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
228                 {       if (format == subtype_formats [k].format)
229                         {       memcpy (data, &(subtype_formats [k]), sizeof (SF_FORMAT_INFO)) ;
230                                 return 0 ;
231                                 } ;
232                         } ;
233                 } ;
234
235         memset (data, 0, sizeof (SF_FORMAT_INFO)) ;
236
237         return SFE_BAD_CONTROL_CMD ;
238 } /* psf_get_format_info */
239
240 /*==============================================================================
241 */
242
243 double
244 psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
245 {       sf_count_t      position ;
246         double          max_val, temp, *data ;
247         int                     k, len, readcount, save_state ;
248
249         /* If the file is not seekable, there is nothing we can do. */
250         if (! psf->sf.seekable)
251         {       psf->error = SFE_NOT_SEEKABLE ;
252                 return  0.0 ;
253                 } ;
254
255         if (! psf->read_double)
256         {       psf->error = SFE_UNIMPLEMENTED ;
257                 return  0.0 ;
258                 } ;
259
260         save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
261         sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
262
263         /* Brute force. Read the whole file and find the biggest sample. */
264         /* Get current position in file */
265         position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ;
266         /* Go to start of file. */
267         sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ;
268
269         data = psf->u.dbuf ;
270         len = ARRAY_LEN (psf->u.dbuf) ;
271
272         for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */)
273         {       readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
274                 for (k = 0 ; k < readcount ; k++)
275                 {       temp = fabs (data [k]) ;
276                         max_val = temp > max_val ? temp : max_val ;
277                         } ;
278                 } ;
279
280         /* Return to SNDFILE to original state. */
281         sf_seek ((SNDFILE*) psf, position, SEEK_SET) ;
282         sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
283
284         return  max_val ;
285 } /* psf_calc_signal_max */
286
287 int
288 psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
289 {       sf_count_t      position ;
290         double          temp, *data ;
291         int                     k, len, readcount, save_state ;
292         int                     chan ;
293
294         /* If the file is not seekable, there is nothing we can do. */
295         if (! psf->sf.seekable)
296                 return (psf->error = SFE_NOT_SEEKABLE) ;
297
298         if (! psf->read_double)
299                 return (psf->error = SFE_UNIMPLEMENTED) ;
300
301         save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
302         sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
303
304         memset (peaks, 0, sizeof (double) * psf->sf.channels) ;
305
306         /* Brute force. Read the whole file and find the biggest sample for each channel. */
307         position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */
308         sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ;                 /* Go to start of file. */
309
310         len = ARRAY_LEN (psf->u.dbuf) ;
311
312         data = psf->u.dbuf ;
313
314         chan = 0 ;
315         readcount = len ;
316         while (readcount > 0)
317         {       readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
318                 for (k = 0 ; k < readcount ; k++)
319                 {       temp = fabs (data [k]) ;
320                         peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ;
321                         chan = (chan + 1) % psf->sf.channels ;
322                         } ;
323                 } ;
324
325         sf_seek ((SNDFILE*) psf, position, SEEK_SET) ;          /* Return to original position. */
326
327         sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
328
329         return  0 ;
330 } /* psf_calc_max_all_channels */
331
332 int
333 psf_get_signal_max (SF_PRIVATE *psf, double *peak)
334 {       int k ;
335
336         if (psf->peak_info == NULL)
337                 return SF_FALSE ;
338
339         peak [0] = psf->peak_info->peaks [0].value ;
340
341         for (k = 1 ; k < psf->sf.channels ; k++)
342                 peak [0] = SF_MAX (peak [0], psf->peak_info->peaks [k].value) ;
343
344         return SF_TRUE ;
345 } /* psf_get_signal_max */
346
347 int
348 psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks)
349 {       int k ;
350
351         if (psf->peak_info == NULL)
352                 return SF_FALSE ;
353
354         for (k = 0 ; k < psf->sf.channels ; k++)
355                 peaks [k] = psf->peak_info->peaks [k].value ;
356
357         return SF_TRUE ;
358 }  /* psf_get_max_all_channels */
359
360
361 /*
362 ** Do not edit or modify anything in this comment block.
363 ** The arch-tag line is a file identity tag for the GNU Arch 
364 ** revision control system.
365 **
366 ** arch-tag: 0aae0d9d-ab2b-4d70-ade3-47a534666f8e
367 */