1 /* libSoX libsndfile formats.
3 * Copyright 2007 Reuben Thomas <rrt@sc3d.org>
4 * Copyright 1999-2005 Erik de Castro Lopo <eridk@mega-nerd.com>
6 * This library is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or (at
9 * your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #define LOG_MAX 2048 /* As per the SFC_GET_LOG_INFO example */
31 #if !defined(HAVE_LIBLTDL)
35 static const char* const sndfile_library_names
[] =
46 #define SNDFILE_FUNC LSX_DLENTRY_DYNAMIC
47 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
49 #define SNDFILE_FUNC LSX_DLENTRY_STATIC
51 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STATIC
53 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
55 #endif /* DL_SNDFILE */
57 #define SNDFILE_FUNC_OPEN(f,x) \
58 SNDFILE_FUNC(f,x, SNDFILE*, sf_open_virtual, (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data))
60 #define SNDFILE_FUNC_ENTRIES(f,x) \
61 SNDFILE_FUNC_OPEN(f,x) \
62 SNDFILE_FUNC_STOP(f,x, int, sf_stop, (SNDFILE *sndfile)) \
63 SNDFILE_FUNC(f,x, int, sf_close, (SNDFILE *sndfile)) \
64 SNDFILE_FUNC(f,x, int, sf_format_check, (const SF_INFO *info)) \
65 SNDFILE_FUNC(f,x, int, sf_command, (SNDFILE *sndfile, int command, void *data, int datasize)) \
66 SNDFILE_FUNC(f,x, sf_count_t, sf_read_int, (SNDFILE *sndfile, int *ptr, sf_count_t items)) \
67 SNDFILE_FUNC(f,x, sf_count_t, sf_write_int, (SNDFILE *sndfile, const int *ptr, sf_count_t items)) \
68 SNDFILE_FUNC(f,x, sf_count_t, sf_seek, (SNDFILE *sndfile, sf_count_t frames, int whence)) \
69 SNDFILE_FUNC(f,x, const char*, sf_strerror, (SNDFILE *sndfile))
71 /* Private data for sndfile files */
76 char const * log_buffer_ptr
;
77 LSX_DLENTRIES_TO_PTRS(SNDFILE_FUNC_ENTRIES
, sndfile_dl
);
81 * Drain LSF's wonderful log buffer
83 static void drain_log_buffer(sox_format_t
* ft
)
85 priv_t
* sf
= (priv_t
*)ft
->priv
;
86 sf
->sf_command(sf
->sf_file
, SFC_GET_LOG_INFO
, sf
->log_buffer
, LOG_MAX
);
87 while (*sf
->log_buffer_ptr
) {
88 static char const warning_prefix
[] = "*** Warning : ";
89 char const * end
= strchr(sf
->log_buffer_ptr
, '\n');
91 end
= strchr(sf
->log_buffer_ptr
, '\0');
92 if (!strncmp(sf
->log_buffer_ptr
, warning_prefix
, strlen(warning_prefix
))) {
93 sf
->log_buffer_ptr
+= strlen(warning_prefix
);
94 lsx_warn("`%s': %.*s",
95 ft
->filename
, (int)(end
- sf
->log_buffer_ptr
), sf
->log_buffer_ptr
);
97 lsx_debug("`%s': %.*s",
98 ft
->filename
, (int)(end
- sf
->log_buffer_ptr
), sf
->log_buffer_ptr
);
99 sf
->log_buffer_ptr
= end
;
100 if (*sf
->log_buffer_ptr
== '\n')
101 ++sf
->log_buffer_ptr
;
105 /* Make libsndfile subtype from sample encoding and size */
106 static int ft_enc(unsigned size
, sox_encoding_t e
)
108 if (e
== SOX_ENCODING_ULAW
&& size
== 8) return SF_FORMAT_ULAW
;
109 if (e
== SOX_ENCODING_ALAW
&& size
== 8) return SF_FORMAT_ALAW
;
110 if (e
== SOX_ENCODING_SIGN2
&& size
== 8) return SF_FORMAT_PCM_S8
;
111 if (e
== SOX_ENCODING_SIGN2
&& size
== 16) return SF_FORMAT_PCM_16
;
112 if (e
== SOX_ENCODING_SIGN2
&& size
== 24) return SF_FORMAT_PCM_24
;
113 if (e
== SOX_ENCODING_SIGN2
&& size
== 32) return SF_FORMAT_PCM_32
;
114 if (e
== SOX_ENCODING_UNSIGNED
&& size
== 8) return SF_FORMAT_PCM_U8
;
115 if (e
== SOX_ENCODING_FLOAT
&& size
== 32) return SF_FORMAT_FLOAT
;
116 if (e
== SOX_ENCODING_FLOAT
&& size
== 64) return SF_FORMAT_DOUBLE
;
117 if (e
== SOX_ENCODING_G721
&& size
== 4) return SF_FORMAT_G721_32
;
118 if (e
== SOX_ENCODING_G723
&& size
== 3) return SF_FORMAT_G723_24
;
119 if (e
== SOX_ENCODING_G723
&& size
== 5) return SF_FORMAT_G723_40
;
120 if (e
== SOX_ENCODING_MS_ADPCM
&& size
== 4) return SF_FORMAT_MS_ADPCM
;
121 if (e
== SOX_ENCODING_IMA_ADPCM
&& size
== 4) return SF_FORMAT_IMA_ADPCM
;
122 if (e
== SOX_ENCODING_OKI_ADPCM
&& size
== 4) return SF_FORMAT_VOX_ADPCM
;
123 if (e
== SOX_ENCODING_DPCM
&& size
== 8) return SF_FORMAT_DPCM_8
;
124 if (e
== SOX_ENCODING_DPCM
&& size
== 16) return SF_FORMAT_DPCM_16
;
125 if (e
== SOX_ENCODING_DWVW
&& size
== 12) return SF_FORMAT_DWVW_12
;
126 if (e
== SOX_ENCODING_DWVW
&& size
== 16) return SF_FORMAT_DWVW_16
;
127 if (e
== SOX_ENCODING_DWVW
&& size
== 24) return SF_FORMAT_DWVW_24
;
128 if (e
== SOX_ENCODING_DWVWN
&& size
== 0) return SF_FORMAT_DWVW_N
;
129 if (e
== SOX_ENCODING_GSM
&& size
== 0) return SF_FORMAT_GSM610
;
130 if (e
== SOX_ENCODING_FLAC
&& size
== 8) return SF_FORMAT_PCM_S8
;
131 if (e
== SOX_ENCODING_FLAC
&& size
== 16) return SF_FORMAT_PCM_16
;
132 if (e
== SOX_ENCODING_FLAC
&& size
== 24) return SF_FORMAT_PCM_24
;
133 if (e
== SOX_ENCODING_FLAC
&& size
== 32) return SF_FORMAT_PCM_32
;
134 return 0; /* Bad encoding */
137 /* Convert format's encoding type to libSoX encoding type & size. */
138 static sox_encoding_t
sox_enc(int ft_encoding
, unsigned * size
)
140 int sub
= ft_encoding
& SF_FORMAT_SUBMASK
;
141 int type
= ft_encoding
& SF_FORMAT_TYPEMASK
;
143 if (type
== SF_FORMAT_FLAC
) switch (sub
) {
144 case SF_FORMAT_PCM_S8
: *size
= 8; return SOX_ENCODING_FLAC
;
145 case SF_FORMAT_PCM_16
: *size
= 16; return SOX_ENCODING_FLAC
;
146 case SF_FORMAT_PCM_24
: *size
= 24; return SOX_ENCODING_FLAC
;
149 case SF_FORMAT_ULAW
: *size
= 8; return SOX_ENCODING_ULAW
;
150 case SF_FORMAT_ALAW
: *size
= 8; return SOX_ENCODING_ALAW
;
151 case SF_FORMAT_PCM_S8
: *size
= 8; return SOX_ENCODING_SIGN2
;
152 case SF_FORMAT_PCM_16
: *size
= 16; return SOX_ENCODING_SIGN2
;
153 case SF_FORMAT_PCM_24
: *size
= 24; return SOX_ENCODING_SIGN2
;
154 case SF_FORMAT_PCM_32
: *size
= 32; return SOX_ENCODING_SIGN2
;
155 case SF_FORMAT_PCM_U8
: *size
= 8; return SOX_ENCODING_UNSIGNED
;
156 case SF_FORMAT_FLOAT
: *size
= 32; return SOX_ENCODING_FLOAT
;
157 case SF_FORMAT_DOUBLE
: *size
= 64; return SOX_ENCODING_FLOAT
;
158 case SF_FORMAT_G721_32
: *size
= 4; return SOX_ENCODING_G721
;
159 case SF_FORMAT_G723_24
: *size
= 3; return SOX_ENCODING_G723
;
160 case SF_FORMAT_G723_40
: *size
= 5; return SOX_ENCODING_G723
;
161 case SF_FORMAT_MS_ADPCM
: *size
= 4; return SOX_ENCODING_MS_ADPCM
;
162 case SF_FORMAT_IMA_ADPCM
: *size
= 4; return SOX_ENCODING_IMA_ADPCM
;
163 case SF_FORMAT_VOX_ADPCM
: *size
= 4; return SOX_ENCODING_OKI_ADPCM
;
164 case SF_FORMAT_DPCM_8
: *size
= 8; return SOX_ENCODING_DPCM
;
165 case SF_FORMAT_DPCM_16
: *size
= 16; return SOX_ENCODING_DPCM
;
166 case SF_FORMAT_DWVW_12
: *size
= 12; return SOX_ENCODING_DWVW
;
167 case SF_FORMAT_DWVW_16
: *size
= 16; return SOX_ENCODING_DWVW
;
168 case SF_FORMAT_DWVW_24
: *size
= 24; return SOX_ENCODING_DWVW
;
169 case SF_FORMAT_DWVW_N
: *size
= 0; return SOX_ENCODING_DWVWN
;
170 case SF_FORMAT_GSM610
: *size
= 0; return SOX_ENCODING_GSM
;
171 default : *size
= 0; return SOX_ENCODING_UNKNOWN
;
180 { "aif", SF_FORMAT_AIFF
},
181 { "aiff", SF_FORMAT_AIFF
},
182 { "wav", SF_FORMAT_WAV
},
183 { "au", SF_FORMAT_AU
},
184 { "snd", SF_FORMAT_AU
},
185 { "caf", SF_FORMAT_CAF
},
186 { "flac", SF_FORMAT_FLAC
},
187 { "wve", SF_FORMAT_WVE
},
188 { "ogg", SF_FORMAT_OGG
},
189 { "svx", SF_FORMAT_SVX
},
190 { "8svx", SF_FORMAT_SVX
},
191 { "paf", SF_ENDIAN_BIG
| SF_FORMAT_PAF
},
192 { "fap", SF_ENDIAN_LITTLE
| SF_FORMAT_PAF
},
193 { "gsm", SF_FORMAT_RAW
| SF_FORMAT_GSM610
},
194 { "nist", SF_FORMAT_NIST
},
195 { "sph", SF_FORMAT_NIST
},
196 { "ircam", SF_FORMAT_IRCAM
},
197 { "sf", SF_FORMAT_IRCAM
},
198 { "voc", SF_FORMAT_VOC
},
199 { "w64", SF_FORMAT_W64
},
200 { "raw", SF_FORMAT_RAW
},
201 { "mat4", SF_FORMAT_MAT4
},
202 { "mat5", SF_FORMAT_MAT5
},
203 { "mat", SF_FORMAT_MAT4
},
204 { "pvf", SF_FORMAT_PVF
},
205 { "sds", SF_FORMAT_SDS
},
206 { "sd2", SF_FORMAT_SD2
},
207 { "vox", SF_FORMAT_RAW
| SF_FORMAT_VOX_ADPCM
},
208 { "xi", SF_FORMAT_XI
}
211 static int sf_stop_stub(SNDFILE
*sndfile UNUSED
)
216 static sf_count_t
vio_get_filelen(void *user_data
)
218 sox_format_t
*ft
= (sox_format_t
*)user_data
;
220 /* lsf excepts unbuffered I/O behavior for get_filelen() so force that */
223 return (sf_count_t
)lsx_filelength((sox_format_t
*)user_data
);
226 static sf_count_t
vio_seek(sf_count_t offset
, int whence
, void *user_data
)
228 return lsx_seeki((sox_format_t
*)user_data
, (off_t
)offset
, whence
);
231 static sf_count_t
vio_read(void *ptr
, sf_count_t count
, void *user_data
)
233 return lsx_readbuf((sox_format_t
*)user_data
, ptr
, (size_t)count
);
236 static sf_count_t
vio_write(const void *ptr
, sf_count_t count
, void *user_data
)
238 return lsx_writebuf((sox_format_t
*)user_data
, ptr
, (size_t)count
);
241 static sf_count_t
vio_tell(void *user_data
)
243 return lsx_tell((sox_format_t
*)user_data
);
246 static SF_VIRTUAL_IO vio
=
255 /* Convert file name or type to libsndfile format */
256 static int name_to_format(const char *name
)
259 #define FILE_TYPE_BUFLEN (size_t)15
260 char buffer
[FILE_TYPE_BUFLEN
+ 1], *cptr
;
262 if ((cptr
= strrchr(name
, '.')) != NULL
) {
263 strncpy(buffer
, cptr
+ 1, FILE_TYPE_BUFLEN
);
264 buffer
[FILE_TYPE_BUFLEN
] = '\0';
266 for (k
= 0; buffer
[k
]; k
++)
267 buffer
[k
] = tolower((buffer
[k
]));
269 strncpy(buffer
, name
, FILE_TYPE_BUFLEN
);
270 buffer
[FILE_TYPE_BUFLEN
] = '\0';
273 for (k
= 0; k
< (int)(sizeof(format_map
) / sizeof(format_map
[0])); k
++) {
274 if (strcmp(buffer
, format_map
[k
].ext
) == 0)
275 return format_map
[k
].format
;
281 static int start(sox_format_t
* ft
)
283 priv_t
* sf
= (priv_t
*)ft
->priv
;
284 int subtype
= ft_enc(ft
->encoding
.bits_per_sample
? ft
->encoding
.bits_per_sample
: ft
->signal
.precision
, ft
->encoding
.encoding
);
285 int open_library_result
;
290 SNDFILE_FUNC_ENTRIES
,
291 "libsndfile library",
292 sndfile_library_names
,
293 open_library_result
);
294 if (open_library_result
)
297 sf
->log_buffer_ptr
= sf
->log_buffer
= lsx_malloc((size_t)LOG_MAX
);
298 sf
->sf_info
= lsx_calloc(1, sizeof(SF_INFO
));
300 /* Copy format info */
302 if (strcmp(ft
->filetype
, "sndfile") == 0)
303 sf
->sf_info
->format
= name_to_format(ft
->filename
) | subtype
;
305 sf
->sf_info
->format
= name_to_format(ft
->filetype
) | subtype
;
307 sf
->sf_info
->samplerate
= (int)ft
->signal
.rate
;
308 sf
->sf_info
->channels
= ft
->signal
.channels
;
309 if (ft
->signal
.channels
)
310 sf
->sf_info
->frames
= ft
->signal
.length
/ ft
->signal
.channels
;
315 static int check_read_params(sox_format_t
* ft
, unsigned channels
,
316 sox_rate_t rate
, sox_encoding_t encoding
, unsigned bits_per_sample
, uint64_t length
)
318 ft
->signal
.length
= length
;
320 if (channels
&& ft
->signal
.channels
&& ft
->signal
.channels
!= channels
)
321 lsx_warn("`%s': overriding number of channels", ft
->filename
);
322 else ft
->signal
.channels
= channels
;
324 if (rate
&& ft
->signal
.rate
&& ft
->signal
.rate
!= rate
)
325 lsx_warn("`%s': overriding sample rate", ft
->filename
);
326 else ft
->signal
.rate
= rate
;
328 if (encoding
&& ft
->encoding
.encoding
&& ft
->encoding
.encoding
!= encoding
)
329 lsx_warn("`%s': overriding encoding type", ft
->filename
);
330 else ft
->encoding
.encoding
= encoding
;
332 if (bits_per_sample
&& ft
->encoding
.bits_per_sample
&& ft
->encoding
.bits_per_sample
!= bits_per_sample
)
333 lsx_warn("`%s': overriding encoding size", ft
->filename
);
334 ft
->encoding
.bits_per_sample
= bits_per_sample
;
336 if (sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
))
338 lsx_fail_errno(ft
, EINVAL
, "invalid format for this file type");
343 * Open file in sndfile.
345 static int startread(sox_format_t
* ft
)
347 priv_t
* sf
= (priv_t
*)ft
->priv
;
348 unsigned bits_per_sample
;
349 sox_encoding_t encoding
;
352 if (start(ft
) == SOX_EOF
)
355 sf
->sf_file
= sf
->sf_open_virtual(&vio
, SFM_READ
, sf
->sf_info
, ft
);
356 drain_log_buffer(ft
);
358 if (sf
->sf_file
== NULL
) {
359 memset(ft
->sox_errstr
, 0, sizeof(ft
->sox_errstr
));
360 strncpy(ft
->sox_errstr
, sf
->sf_strerror(sf
->sf_file
), sizeof(ft
->sox_errstr
)-1);
365 if (!(encoding
= sox_enc(sf
->sf_info
->format
, &bits_per_sample
))) {
366 lsx_fail_errno(ft
, SOX_EFMT
, "unsupported sndfile encoding %#x", sf
->sf_info
->format
);
370 /* Don't believe LSF's rate for raw files */
371 if ((sf
->sf_info
->format
& SF_FORMAT_TYPEMASK
) == SF_FORMAT_RAW
&& !ft
->signal
.rate
) {
372 lsx_warn("`%s': sample rate not specified; trying 8kHz", ft
->filename
);
375 else rate
= sf
->sf_info
->samplerate
;
377 if ((sf
->sf_info
->format
& SF_FORMAT_SUBMASK
) == SF_FORMAT_FLOAT
) {
378 sf
->sf_command(sf
->sf_file
, SFC_SET_SCALE_FLOAT_INT_READ
, NULL
, SF_TRUE
);
379 sf
->sf_command(sf
->sf_file
, SFC_SET_CLIPPING
, NULL
, SF_TRUE
);
383 sox_append_comments(&ft
->oob
.comments
, buf
);
386 return check_read_params(ft
, (unsigned)sf
->sf_info
->channels
, rate
,
387 encoding
, bits_per_sample
, (uint64_t)(sf
->sf_info
->frames
* sf
->sf_info
->channels
));
391 * Read up to len samples of type sox_sample_t from file into buf[].
392 * Return number of samples read.
394 static size_t read_samples(sox_format_t
* ft
, sox_sample_t
*buf
, size_t len
)
396 priv_t
* sf
= (priv_t
*)ft
->priv
;
397 /* FIXME: We assume int == sox_sample_t here */
398 return (size_t)sf
->sf_read_int(sf
->sf_file
, (int *)buf
, (sf_count_t
)len
);
402 * Close file for libsndfile (this doesn't close the file handle)
404 static int stopread(sox_format_t
* ft
)
406 priv_t
* sf
= (priv_t
*)ft
->priv
;
407 sf
->sf_stop(sf
->sf_file
);
408 drain_log_buffer(ft
);
409 sf
->sf_close(sf
->sf_file
);
410 LSX_DLLIBRARY_CLOSE(sf
, sndfile_dl
);
414 static int startwrite(sox_format_t
* ft
)
416 priv_t
* sf
= (priv_t
*)ft
->priv
;
418 if (start(ft
) == SOX_EOF
)
421 /* If output format is invalid, try to find a sensible default */
422 if (!sf
->sf_format_check(sf
->sf_info
)) {
423 SF_FORMAT_INFO format_info
;
426 sf
->sf_command(sf
->sf_file
, SFC_GET_SIMPLE_FORMAT_COUNT
, &count
, (int) sizeof(int));
427 for (i
= 0; i
< count
; i
++) {
428 format_info
.format
= i
;
429 sf
->sf_command(sf
->sf_file
, SFC_GET_SIMPLE_FORMAT
, &format_info
, (int) sizeof(format_info
));
430 if ((format_info
.format
& SF_FORMAT_TYPEMASK
) == (sf
->sf_info
->format
& SF_FORMAT_TYPEMASK
)) {
431 sf
->sf_info
->format
= format_info
.format
;
432 /* FIXME: Print out exactly what we chose, needs sndfile ->
433 sox encoding conversion functions */
438 if (!sf
->sf_format_check(sf
->sf_info
)) {
439 lsx_fail("cannot find a usable output encoding");
442 if ((sf
->sf_info
->format
& SF_FORMAT_TYPEMASK
) != SF_FORMAT_RAW
)
443 lsx_warn("cannot use desired output encoding, choosing default");
446 sf
->sf_file
= sf
->sf_open_virtual(&vio
, SFM_WRITE
, sf
->sf_info
, ft
);
447 drain_log_buffer(ft
);
449 if (sf
->sf_file
== NULL
) {
450 memset(ft
->sox_errstr
, 0, sizeof(ft
->sox_errstr
));
451 strncpy(ft
->sox_errstr
, sf
->sf_strerror(sf
->sf_file
), sizeof(ft
->sox_errstr
)-1);
456 if ((sf
->sf_info
->format
& SF_FORMAT_SUBMASK
) == SF_FORMAT_FLOAT
)
457 sf
->sf_command(sf
->sf_file
, SFC_SET_SCALE_INT_FLOAT_WRITE
, NULL
, SF_TRUE
);
463 * Write len samples of type sox_sample_t from buf[] to file.
464 * Return number of samples written.
466 static size_t write_samples(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t len
)
468 priv_t
* sf
= (priv_t
*)ft
->priv
;
469 /* FIXME: We assume int == sox_sample_t here */
470 return (size_t)sf
->sf_write_int(sf
->sf_file
, (int *)buf
, (sf_count_t
)len
);
474 * Close file for libsndfile (this doesn't close the file handle)
476 static int stopwrite(sox_format_t
* ft
)
478 priv_t
* sf
= (priv_t
*)ft
->priv
;
479 sf
->sf_stop(sf
->sf_file
);
480 drain_log_buffer(ft
);
481 sf
->sf_close(sf
->sf_file
);
482 LSX_DLLIBRARY_CLOSE(sf
, sndfile_dl
);
486 static int seek(sox_format_t
* ft
, uint64_t offset
)
488 priv_t
* sf
= (priv_t
*)ft
->priv
;
489 sf
->sf_seek(sf
->sf_file
, (sf_count_t
)(offset
/ ft
->signal
.channels
), SEEK_CUR
);
493 LSX_FORMAT_HANDLER(sndfile
)
495 static char const * const names
[] = {
496 "sndfile", /* Special type to force use of sndfile for the following: */
497 /* LSF implementation of formats built in to SoX: */
509 /* LSF wrappers of formats already wrapped in SoX: */
516 static unsigned const write_encodings
[] = {
517 SOX_ENCODING_SIGN2
, 16, 24, 32, 8, 0,
518 SOX_ENCODING_UNSIGNED
, 8, 0,
519 SOX_ENCODING_FLOAT
, 32, 64, 0,
520 SOX_ENCODING_ALAW
, 8, 0,
521 SOX_ENCODING_ULAW
, 8, 0,
522 SOX_ENCODING_IMA_ADPCM
, 4, 0,
523 SOX_ENCODING_MS_ADPCM
, 4, 0,
524 SOX_ENCODING_OKI_ADPCM
, 4, 0,
528 static sox_format_handler_t
const format
= {SOX_LIB_VERSION_CODE
,
529 "Pseudo format to use libsndfile", names
, 0,
530 startread
, read_samples
, stopread
,
531 startwrite
, write_samples
, stopwrite
,
532 seek
, write_encodings
, NULL
, sizeof(priv_t
)