wav: simplify extended fmt chunk handling [bug #198]
[sox.git] / src / sndfile.c
blobb48084ffd91c34793d41c727177d106d0bdc5098
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
21 #include "sox_i.h"
23 #include <assert.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <sndfile.h>
29 #define LOG_MAX 2048 /* As per the SFC_GET_LOG_INFO example */
31 #if !defined(HAVE_LIBLTDL)
32 #undef DL_SNDFILE
33 #endif
35 static const char* const sndfile_library_names[] =
37 #ifdef DL_SNDFILE
38 "libsndfile",
39 "libsndfile-1",
40 "cygsndfile-1",
41 #endif
42 NULL
45 #ifdef DL_SNDFILE
46 #define SNDFILE_FUNC LSX_DLENTRY_DYNAMIC
47 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
48 #else
49 #define SNDFILE_FUNC LSX_DLENTRY_STATIC
50 #ifdef HACKED_LSF
51 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STATIC
52 #else
53 #define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
54 #endif
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 */
72 typedef struct {
73 SNDFILE *sf_file;
74 SF_INFO *sf_info;
75 char * log_buffer;
76 char const * log_buffer_ptr;
77 LSX_DLENTRIES_TO_PTRS(SNDFILE_FUNC_ENTRIES, sndfile_dl);
78 } priv_t;
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');
90 if (!end)
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);
96 } else
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;
148 switch (sub) {
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;
175 static struct {
176 const char *ext;
177 int format;
178 } format_map[] =
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)
213 return 1;
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 */
221 lsx_flush(ft);
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 =
248 vio_get_filelen,
249 vio_seek,
250 vio_read,
251 vio_write,
252 vio_tell
255 /* Convert file name or type to libsndfile format */
256 static int name_to_format(const char *name)
258 int k;
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]));
268 } else {
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;
278 return 0;
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;
287 LSX_DLLIBRARY_OPEN(
289 sndfile_dl,
290 SNDFILE_FUNC_ENTRIES,
291 "libsndfile library",
292 sndfile_library_names,
293 open_library_result);
294 if (open_library_result)
295 return SOX_EOF;
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 */
301 if (subtype) {
302 if (strcmp(ft->filetype, "sndfile") == 0)
303 sf->sf_info->format = name_to_format(ft->filename) | subtype;
304 else
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;
312 return SOX_SUCCESS;
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))
337 return SOX_SUCCESS;
338 lsx_fail_errno(ft, EINVAL, "invalid format for this file type");
339 return SOX_EOF;
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;
350 sox_rate_t rate;
352 if (start(ft) == SOX_EOF)
353 return 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);
361 free(sf->sf_file);
362 return SOX_EOF;
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);
367 return SOX_EOF;
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);
373 rate = 8000;
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);
382 #if 0 /* FIXME */
383 sox_append_comments(&ft->oob.comments, buf);
384 #endif
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);
411 return SOX_SUCCESS;
414 static int startwrite(sox_format_t * ft)
416 priv_t * sf = (priv_t *)ft->priv;
418 if (start(ft) == SOX_EOF)
419 return 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;
424 int i, count;
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 */
434 break;
438 if (!sf->sf_format_check(sf->sf_info)) {
439 lsx_fail("cannot find a usable output encoding");
440 return SOX_EOF;
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);
452 free(sf->sf_file);
453 return SOX_EOF;
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);
459 return SOX_SUCCESS;
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);
483 return SOX_SUCCESS;
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);
490 return SOX_SUCCESS;
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: */
498 /* "aif", */
499 /* "au", */
500 /* "gsm", */
501 /* "nist", */
502 /* "raw", */
503 /* "sf", "ircam", */
504 /* "snd", */
505 /* "svx", */
506 /* "voc", */
507 /* "vox", */
508 /* "wav", */
509 /* LSF wrappers of formats already wrapped in SoX: */
510 /* "flac", */
512 "sds", /* ?? */
513 NULL
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,
525 SOX_ENCODING_GSM, 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)
535 return &format;