1 /* Stub code to access libsndfile functions from OCaml */
4 ** Copyright (c) 2006, 2007 Erik de Castro Lopo <erikd at mega-nerd dot com>
5 ** WWW: http://www.mega-nerd.com/libsndfile/Ocaml/
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2 of the License, or (at your option) any later version.
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <caml/mlvalues.h>
23 #include <caml/alloc.h>
24 #include <caml/memory.h>
25 #include <caml/custom.h>
26 #include <caml/fail.h>
27 #include <caml/callback.h>
28 #include <caml/bigarray.h>
35 #define CAML_SNDFILE_VERSION "v0.1"
37 #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof (x [0])))
45 static void caml_sf_finalize (value file
) ;
46 static int caml_val_to_major_format (int f
) ;
47 static int caml_val_to_minor_format (int f
) ;
49 static struct custom_operations sndfile_custom_ops
=
51 /* identifier */ "SNDFILE/CAMLinterface/" CAML_SNDFILE_VERSION
"/sndfile",
52 /* finalize */ caml_sf_finalize
,
56 /* deserialize */ NULL
60 caml_sf_format_e (value v_major
, value v_minor
, value v_endian
)
62 int minor
, major
, endian
;
64 CAMLparam3 (v_major
, v_minor
, v_endian
) ;
66 minor
= caml_val_to_minor_format (Int_val (v_minor
)) ;
67 major
= caml_val_to_major_format (Int_val (v_major
)) ;
68 endian
= (Int_val (v_endian
) << 28) & SF_FORMAT_ENDMASK
;
70 CAMLreturn (Val_int (endian
+ major
+ minor
)) ;
71 } /* caml_sf_format_e */
74 caml_sf_open_private (value v_filename
, value v_mode
, value v_fmt
, value v_channels
, value v_samplerate
)
80 CAMLparam5 (v_filename
, v_mode
, v_fmt
, v_channels
, v_samplerate
) ;
82 v_wrapper
= caml_alloc_custom (&sndfile_custom_ops
, sizeof (SF_WRAPPER
), sizeof (SF_WRAPPER
), sizeof (SF_WRAPPER
)) ;
83 wrapper
= Data_custom_val (v_wrapper
) ;
85 failwith ("Sndfile.sf_open : caml_alloc_custom failed.") ;
87 memset (wrapper
, 0, sizeof (*wrapper
)) ;
89 switch (Int_val (v_mode
))
95 wrapper
->info
.format
= Int_val (v_fmt
) ;
96 wrapper
->info
.channels
= Int_val (v_channels
) ;
97 wrapper
->info
.samplerate
= Int_val (v_samplerate
) ;
101 wrapper
->info
.format
= Int_val (v_fmt
) ;
102 wrapper
->info
.channels
= Int_val (v_channels
) ;
103 wrapper
->info
.samplerate
= Int_val (v_samplerate
) ;
109 wrapper
->file
= sf_open (String_val (v_filename
), mode
, &wrapper
->info
) ;
111 if (wrapper
->file
== NULL
)
112 { int errnum
= sf_error (NULL
) ;
113 const char *err_str
= sf_error_number (errnum
) ;
118 value sferr
= caml_alloc_tuple (2) ;
121 { case SF_ERR_NO_ERROR
:
122 case SF_ERR_UNRECOGNISED_FORMAT
:
124 case SF_ERR_MALFORMED_FILE
:
125 case SF_ERR_UNSUPPORTED_ENCODING
:
128 errnum
= SF_ERR_UNSUPPORTED_ENCODING
+ 1 ;
132 Store_field (sferr
, 0, caml_copy_nativeint (errnum
)) ;
133 Store_field (sferr
, 1, caml_copy_string (err_str
)) ;
135 value
*exn
= caml_named_value ("sndfile_open_exn") ;
137 failwith ("asdasdasdas") ;
139 caml_raise_with_arg (*exn
, sferr
) ;
142 CAMLreturn (v_wrapper
) ;
143 } /* caml_sf_open_private */
146 caml_sf_close (value v_wrapper
)
148 SF_WRAPPER
*wrapper
;
150 CAMLparam1 (v_wrapper
) ;
151 wrapper
= Data_custom_val (v_wrapper
) ;
153 if (wrapper
->file
!= NULL
)
154 { sf_close (wrapper
->file
) ;
155 wrapper
->file
= NULL
;
158 CAMLreturn (Val_unit
) ;
159 } /* caml_sf_close */
161 /* Pulled from ocaml-cairo sources. Not sure how portable/reliable this is. */
162 #define Double_array_val(v) ((double *)(v))
163 #define Double_array_length(v) (Wosize_val(v) / Double_wosize)
166 caml_sf_read (value v_wrapper
, value v_data
)
168 SF_WRAPPER
*wrapper
;
171 CAMLparam2 (v_wrapper
, v_data
) ;
172 wrapper
= Data_custom_val (v_wrapper
) ;
174 count
= sf_read_double (wrapper
->file
, Double_array_val (v_data
), Double_array_length (v_data
)) ;
176 CAMLreturn (Val_int (count
)) ;
180 caml_sf_write (value v_wrapper
, value v_data
)
182 SF_WRAPPER
*wrapper
;
185 CAMLparam2 (v_wrapper
, v_data
) ;
186 wrapper
= Data_custom_val (v_wrapper
) ;
188 count
= sf_write_double (wrapper
->file
, Double_array_val (v_data
), Double_array_length (v_data
)) ;
190 CAMLreturn (Val_int (count
)) ;
191 } /* caml_sf_write */
194 caml_sf_frames (value v_wrapper
)
196 SF_WRAPPER
*wrapper
;
197 sf_count_t frames
= 0 ;
199 CAMLparam1 (v_wrapper
) ;
200 wrapper
= Data_custom_val (v_wrapper
) ;
202 if (wrapper
->file
!= NULL
)
203 frames
= wrapper
->info
.frames
;
205 CAMLreturn (caml_copy_int64 (frames
)) ;
206 } /* caml_sf_frames */
209 caml_sf_samplerate (value v_wrapper
)
211 SF_WRAPPER
*wrapper
;
214 CAMLparam1 (v_wrapper
) ;
215 wrapper
= Data_custom_val (v_wrapper
) ;
217 if (wrapper
->file
!= NULL
)
218 samplerate
= wrapper
->info
.samplerate
;
220 CAMLreturn (Val_int (samplerate
)) ;
221 } /* caml_sf_samplerate */
224 caml_sf_channels (value v_wrapper
)
226 SF_WRAPPER
*wrapper
;
229 CAMLparam1 (v_wrapper
) ;
230 wrapper
= Data_custom_val (v_wrapper
) ;
232 if (wrapper
->file
!= NULL
)
233 channels
= wrapper
->info
.channels
;
235 CAMLreturn (Val_int (channels
)) ;
236 } /* caml_sf_channels */
239 caml_sf_seek (value v_wrapper
, value v_pos
, value v_mode
)
241 SF_WRAPPER
*wrapper
;
245 CAMLparam3 (v_wrapper
, v_pos
, v_mode
) ;
247 wrapper
= Data_custom_val (v_wrapper
) ;
248 mode
= Int_val (v_mode
) ;
249 pos
= Int64_val (v_pos
) ;
251 pos
= sf_seek (wrapper
->file
, pos
, mode
) ;
253 CAMLreturn (Val_int (pos
)) ;
257 caml_sf_compare (value v_wrapper1
, value v_wrapper2
)
259 SF_WRAPPER
*wrapper1
, *wrapper2
;
261 CAMLparam2 (v_wrapper1
, v_wrapper2
) ;
263 wrapper1
= Data_custom_val (v_wrapper1
) ;
264 wrapper2
= Data_custom_val (v_wrapper2
) ;
266 CAMLreturn (Val_int (wrapper2
- wrapper1
)) ;
267 } /* caml_sf_compare */
269 /*==============================================================================
273 caml_sf_finalize (value v_wrapper
)
275 SF_WRAPPER
*wrapper
;
277 wrapper
= Data_custom_val (v_wrapper
) ;
279 if (wrapper
->file
!= NULL
)
280 { sf_close (wrapper
->file
) ;
281 wrapper
->file
= NULL
;
284 } /* caml_sf_finalize */
288 caml_val_to_major_format (int f
)
289 { static int format
[] =
291 0x010000, /* SF_FORMAT_WAV */
292 0x020000, /* SF_FORMAT_AIFF */
293 0x030000, /* SF_FORMAT_AU */
294 0x040000, /* SF_FORMAT_RAW */
295 0x050000, /* SF_FORMAT_PAF */
296 0x060000, /* SF_FORMAT_SVX */
297 0x070000, /* SF_FORMAT_NIST */
298 0x080000, /* SF_FORMAT_VOC */
299 0x0A0000, /* SF_FORMAT_IRCAM */
300 0x0B0000, /* SF_FORMAT_W64 */
301 0x0C0000, /* SF_FORMAT_MAT4 */
302 0x0D0000, /* SF_FORMAT_MAT5 */
303 0x0E0000, /* SF_FORMAT_PVF */
304 0x0F0000, /* SF_FORMAT_XI */
305 0x100000, /* SF_FORMAT_HTK */
306 0x110000, /* SF_FORMAT_SDS */
307 0x120000, /* SF_FORMAT_AVR */
308 0x130000, /* SF_FORMAT_WAVEX */
309 0x160000, /* SF_FORMAT_SD2 */
310 0x170000, /* SF_FORMAT_FLAC */
311 0x180000 /* SF_FORMAT_CAF */
314 if (f
< 0 || f
>= ARRAY_LEN (format
))
318 } /* caml_val_to_major_format */
321 caml_val_to_minor_format (int f
)
322 { static int format
[] =
324 0x0001, /* SF_FORMAT_PCM_S8 */
325 0x0002, /* SF_FORMAT_PCM_16 */
326 0x0003, /* SF_FORMAT_PCM_24 */
327 0x0004, /* SF_FORMAT_PCM_32 */
328 0x0005, /* SF_FORMAT_PCM_U8 */
329 0x0006, /* SF_FORMAT_FLOAT */
330 0x0007, /* SF_FORMAT_DOUBLE */
331 0x0010, /* SF_FORMAT_ULAW */
332 0x0011, /* SF_FORMAT_ALAW */
333 0x0012, /* SF_FORMAT_IMA_ADPCM */
334 0x0013, /* SF_FORMAT_MS_ADPCM */
335 0x0020, /* SF_FORMAT_GSM610 */
336 0x0021, /* SF_FORMAT_VOX_ADPCM */
337 0x0030, /* SF_FORMAT_G721_32 */
338 0x0031, /* SF_FORMAT_G723_24 */
339 0x0032, /* SF_FORMAT_G723_40 */
340 0x0040, /* SF_FORMAT_DWVW_12 */
341 0x0041, /* SF_FORMAT_DWVW_16 */
342 0x0042, /* SF_FORMAT_DWVW_24 */
343 0x0043, /* SF_FORMAT_DWVW_N */
344 0x0050, /* SF_FORMAT_DPCM_8 */
345 0x0051, /* SF_FORMAT_DPCM_16 */
348 if (f
< 0 || f
>= ARRAY_LEN (format
))
352 } /* caml_val_to_minor_format */