1 /* Implements the public API for using libSoX file formats.
2 * All public functions & data are prefixed with sox_ .
4 * (c) 2005-8 Chris Bagwell and SoX contributors
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
31 #include <sys/types.h>
45 #define PIPE_AUTO_DETECT_SIZE 256 /* Only as much as we can rewind a pipe */
46 #define AUTO_DETECT_SIZE 4096 /* For seekable file, so no restriction */
48 static char const * auto_detect_format(sox_format_t
* ft
, char const * ext
)
50 char data
[AUTO_DETECT_SIZE
];
51 size_t len
= lsx_readbuf(ft
, data
, ft
->seekable
? sizeof(data
) : PIPE_AUTO_DETECT_SIZE
);
52 #define CHECK(type, p2, l2, d2, p1, l1, d1) if (len >= p1 + l1 && \
53 !memcmp(data + p1, d1, (size_t)l1) && !memcmp(data + p2, d2, (size_t)l2)) return #type;
54 CHECK(voc
, 0, 0, "" , 0, 20, "Creative Voice File\x1a")
55 CHECK(smp
, 0, 0, "" , 0, 17, "SOUND SAMPLE DATA")
56 CHECK(wve
, 0, 0, "" , 0, 15, "ALawSoundFile**")
57 CHECK(gsrt
, 0, 0, "" , 16, 9, "ring.bin")
58 CHECK(amr
-wb
, 0, 0, "" , 0, 9, "#!AMR-WB\n")
59 CHECK(prc
, 0, 0, "" , 0, 8, "\x37\x00\x00\x10\x6d\x00\x00\x10")
60 CHECK(sph
, 0, 0, "" , 0, 7, "NIST_1A")
61 CHECK(amr
-nb
, 0, 0, "" , 0, 6, "#!AMR\n")
62 CHECK(txw
, 0, 0, "" , 0, 6, "LM8953")
63 CHECK(sndt
, 0, 0, "" , 0, 6, "SOUND\x1a")
64 CHECK(vorbis
, 0, 4, "OggS" , 29, 6, "vorbis")
65 CHECK(opus
, 0, 4, "OggS" , 28, 8, "OpusHead")
66 CHECK(speex
, 0, 4, "OggS" , 28, 6, "Speex")
67 CHECK(hcom
,65, 4, "FSSD" , 128,4, "HCOM")
68 CHECK(wav
, 0, 4, "RIFF" , 8, 4, "WAVE")
69 CHECK(wav
, 0, 4, "RIFX" , 8, 4, "WAVE")
70 CHECK(wav
, 0, 4, "RF64" , 8, 4, "WAVE")
71 CHECK(aiff
, 0, 4, "FORM" , 8, 4, "AIFF")
72 CHECK(aifc
, 0, 4, "FORM" , 8, 4, "AIFC")
73 CHECK(8svx
, 0, 4, "FORM" , 8, 4, "8SVX")
74 CHECK(maud
, 0, 4, "FORM" , 8, 4, "MAUD")
75 CHECK(xa
, 0, 0, "" , 0, 4, "XA\0\0")
76 CHECK(xa
, 0, 0, "" , 0, 4, "XAI\0")
77 CHECK(xa
, 0, 0, "" , 0, 4, "XAJ\0")
78 CHECK(au
, 0, 0, "" , 0, 4, ".snd")
79 CHECK(au
, 0, 0, "" , 0, 4, "dns.")
80 CHECK(au
, 0, 0, "" , 0, 4, "\0ds.")
81 CHECK(au
, 0, 0, "" , 0, 4, ".sd\0")
82 CHECK(flac
, 0, 0, "" , 0, 4, "fLaC")
83 CHECK(avr
, 0, 0, "" , 0, 4, "2BIT")
84 CHECK(caf
, 0, 0, "" , 0, 4, "caff")
85 CHECK(wv
, 0, 0, "" , 0, 4, "wvpk")
86 CHECK(paf
, 0, 0, "" , 0, 4, " paf")
87 CHECK(sf
, 0, 0, "" , 0, 4, "\144\243\001\0")
88 CHECK(sf
, 0, 0, "" , 0, 4, "\0\001\243\144")
89 CHECK(sf
, 0, 0, "" , 0, 4, "\144\243\002\0")
90 CHECK(sf
, 0, 0, "" , 0, 4, "\0\002\243\144")
91 CHECK(sf
, 0, 0, "" , 0, 4, "\144\243\003\0")
92 CHECK(sf
, 0, 0, "" , 0, 4, "\0\003\243\144")
93 CHECK(sf
, 0, 0, "" , 0, 4, "\144\243\004\0")
94 CHECK(sox
, 0, 0, "" , 0, 4, ".SoX")
95 CHECK(sox
, 0, 0, "" , 0, 4, "XoS.")
97 if (ext
&& !strcasecmp(ext
, "snd"))
98 CHECK(sndr
, 7, 1, "" , 0, 2, "\0")
102 if (sox_globals
.use_magic
) {
103 static magic_t magic
;
104 char const * filetype
= NULL
;
106 magic
= magic_open(MAGIC_MIME
| MAGIC_SYMLINK
);
108 magic_load(magic
, NULL
);
111 filetype
= magic_buffer(magic
, data
, len
);
112 if (filetype
&& strncmp(filetype
, "application/octet-stream", (size_t)24) &&
113 !lsx_strends(filetype
, "/unknown") &&
114 strncmp(filetype
, "text/plain", (size_t)10) )
117 lsx_debug("libmagic detected %s", filetype
);
123 static sox_encodings_info_t
const s_sox_encodings_info
[] = {
124 {sox_encodings_none
, "n/a" , "Unknown or not applicable"},
125 {sox_encodings_none
, "Signed PCM" , "Signed Integer PCM"},
126 {sox_encodings_none
, "Unsigned PCM" , "Unsigned Integer PCM"},
127 {sox_encodings_none
, "F.P. PCM" , "Floating Point PCM"},
128 {sox_encodings_none
, "F.P. PCM" , "Floating Point (text) PCM"},
129 {sox_encodings_none
, "FLAC" , "FLAC"},
130 {sox_encodings_none
, "HCOM" , "HCOM"},
131 {sox_encodings_none
, "WavPack" , "WavPack"},
132 {sox_encodings_none
, "F.P. WavPack" , "Floating Point WavPack"},
133 {sox_encodings_lossy1
, "u-law" , "u-law"},
134 {sox_encodings_lossy1
, "A-law" , "A-law"},
135 {sox_encodings_lossy1
, "G.721 ADPCM" , "G.721 ADPCM"},
136 {sox_encodings_lossy1
, "G.723 ADPCM" , "G.723 ADPCM"},
137 {sox_encodings_lossy1
, "CL ADPCM (8)" , "CL ADPCM (from 8-bit)"},
138 {sox_encodings_lossy1
, "CL ADPCM (16)", "CL ADPCM (from 16-bit)"},
139 {sox_encodings_lossy1
, "MS ADPCM" , "MS ADPCM"},
140 {sox_encodings_lossy1
, "IMA ADPCM" , "IMA ADPCM"},
141 {sox_encodings_lossy1
, "OKI ADPCM" , "OKI ADPCM"},
142 {sox_encodings_lossy1
, "DPCM" , "DPCM"},
143 {sox_encodings_none
, "DWVW" , "DWVW"},
144 {sox_encodings_none
, "DWVWN" , "DWVWN"},
145 {sox_encodings_lossy2
, "GSM" , "GSM"},
146 {sox_encodings_lossy2
, "MPEG audio" , "MPEG audio (layer I, II or III)"},
147 {sox_encodings_lossy2
, "Vorbis" , "Vorbis"},
148 {sox_encodings_lossy2
, "AMR-WB" , "AMR-WB"},
149 {sox_encodings_lossy2
, "AMR-NB" , "AMR-NB"},
150 {sox_encodings_lossy2
, "CVSD" , "CVSD"},
151 {sox_encodings_lossy2
, "LPC10" , "LPC10"},
152 {sox_encodings_lossy2
, "Opus" , "Opus"},
155 assert_static(array_length(s_sox_encodings_info
) == SOX_ENCODINGS
,
156 SIZE_MISMATCH_BETWEEN_sox_encoding_t_AND_sox_encodings_info
);
158 sox_encodings_info_t
const *
159 sox_get_encodings_info(void)
161 return s_sox_encodings_info
;
164 unsigned sox_precision(sox_encoding_t encoding
, unsigned bits_per_sample
)
167 case SOX_ENCODING_DWVW
: return bits_per_sample
;
168 case SOX_ENCODING_DWVWN
: return !bits_per_sample
? 16: 0; /* ? */
169 case SOX_ENCODING_HCOM
: return !(bits_per_sample
& 7) && (bits_per_sample
>> 3) - 1 < 1? bits_per_sample
: 0;
170 case SOX_ENCODING_WAVPACK
:
171 case SOX_ENCODING_FLAC
: return !(bits_per_sample
& 7) && (bits_per_sample
>> 3) - 1 < 4? bits_per_sample
: 0;
172 case SOX_ENCODING_SIGN2
: return bits_per_sample
<= 32? bits_per_sample
: 0;
173 case SOX_ENCODING_UNSIGNED
: return !(bits_per_sample
& 7) && (bits_per_sample
>> 3) - 1 < 4? bits_per_sample
: 0;
175 case SOX_ENCODING_ALAW
: return bits_per_sample
== 8? 13: 0;
176 case SOX_ENCODING_ULAW
: return bits_per_sample
== 8? 14: 0;
178 case SOX_ENCODING_CL_ADPCM
: return bits_per_sample
? 8: 0;
179 case SOX_ENCODING_CL_ADPCM16
: return bits_per_sample
== 4? 13: 0;
180 case SOX_ENCODING_MS_ADPCM
: return bits_per_sample
== 4? 14: 0;
181 case SOX_ENCODING_IMA_ADPCM
: return bits_per_sample
== 4? 13: 0;
182 case SOX_ENCODING_OKI_ADPCM
: return bits_per_sample
== 4? 12: 0;
183 case SOX_ENCODING_G721
: return bits_per_sample
== 4? 12: 0;
184 case SOX_ENCODING_G723
: return bits_per_sample
== 3? 8:
185 bits_per_sample
== 5? 14: 0;
186 case SOX_ENCODING_CVSD
: return bits_per_sample
== 1? 16: 0;
187 case SOX_ENCODING_DPCM
: return bits_per_sample
; /* ? */
189 case SOX_ENCODING_MP3
: return 0; /* Accept the precision returned by the format. */
191 case SOX_ENCODING_GSM
:
192 case SOX_ENCODING_VORBIS
:
193 case SOX_ENCODING_OPUS
:
194 case SOX_ENCODING_AMR_WB
:
195 case SOX_ENCODING_AMR_NB
:
196 case SOX_ENCODING_LPC10
: return !bits_per_sample
? 16: 0;
198 case SOX_ENCODING_WAVPACKF
:
199 case SOX_ENCODING_FLOAT
: return bits_per_sample
== 32 ? 25: bits_per_sample
== 64 ? 54: 0;
200 case SOX_ENCODING_FLOAT_TEXT
: return !bits_per_sample
? 54: 0;
203 case SOX_ENCODING_UNKNOWN
: break;
208 void sox_init_encodinginfo(sox_encodinginfo_t
* e
)
210 e
->reverse_bytes
= sox_option_default
;
211 e
->reverse_nibbles
= sox_option_default
;
212 e
->reverse_bits
= sox_option_default
;
213 e
->compression
= HUGE_VAL
;
216 /*--------------------------------- Comments ---------------------------------*/
218 size_t sox_num_comments(sox_comments_t comments
)
228 void sox_append_comment(sox_comments_t
* comments
, char const * comment
)
230 size_t n
= sox_num_comments(*comments
);
231 *comments
= lsx_realloc(*comments
, (n
+ 2) * sizeof(**comments
));
233 (*comments
)[n
++] = lsx_strdup(comment
);
237 void sox_append_comments(sox_comments_t
* comments
, char const * comment
)
241 while ((end
= strchr(comment
, '\n'))) {
242 size_t len
= end
- comment
;
243 char * c
= lsx_malloc((len
+ 1) * sizeof(*c
));
244 strncpy(c
, comment
, len
);
246 sox_append_comment(comments
, c
);
251 sox_append_comment(comments
, comment
);
255 sox_comments_t
sox_copy_comments(sox_comments_t comments
)
257 sox_comments_t result
= 0;
259 if (comments
) while (*comments
)
260 sox_append_comment(&result
, *comments
++);
264 void sox_delete_comments(sox_comments_t
* comments
)
266 sox_comments_t p
= *comments
;
274 char * lsx_cat_comments(sox_comments_t comments
)
276 sox_comments_t p
= comments
;
281 len
+= strlen(*p
++) + 1;
283 result
= lsx_calloc(len
? len
: 1, sizeof(*result
));
285 if ((p
= comments
) && *p
) {
288 strcat(strcat(result
, "\n"), *p
);
293 char const * sox_find_comment(sox_comments_t comments
, char const * id
)
295 size_t len
= strlen(id
);
297 if (comments
) for (;*comments
; ++comments
)
298 if (!strncasecmp(*comments
, id
, len
) && (*comments
)[len
] == '=')
299 return *comments
+ len
+ 1;
303 static void set_endiannesses(sox_format_t
* ft
)
305 if (ft
->handler
.flags
& SOX_FILE_ENDIAN
) {
306 sox_bool file_is_bigendian
= !(ft
->handler
.flags
& SOX_FILE_ENDBIG
);
308 if (ft
->encoding
.opposite_endian
) {
309 ft
->encoding
.reverse_bytes
= file_is_bigendian
!= MACHINE_IS_BIGENDIAN
;
310 lsx_report("`%s': overriding file-type byte-order", ft
->filename
);
311 } else if (ft
->encoding
.reverse_bytes
== sox_option_default
) {
312 ft
->encoding
.reverse_bytes
= file_is_bigendian
== MACHINE_IS_BIGENDIAN
;
315 if (ft
->encoding
.opposite_endian
) {
316 ft
->encoding
.reverse_bytes
= sox_option_yes
;
317 lsx_report("`%s': overriding machine byte-order", ft
->filename
);
318 } else if (ft
->encoding
.reverse_bytes
== sox_option_default
) {
319 ft
->encoding
.reverse_bytes
= sox_option_no
;
323 /* FIXME: Change reports to suitable warnings if trying
324 * to override something that can't be overridden. */
326 if (ft
->encoding
.reverse_bits
== sox_option_default
)
327 ft
->encoding
.reverse_bits
= !!(ft
->handler
.flags
& SOX_FILE_BIT_REV
);
328 else if (ft
->encoding
.reverse_bits
== !(ft
->handler
.flags
& SOX_FILE_BIT_REV
))
329 lsx_report("`%s': overriding file-type bit-order", ft
->filename
);
331 if (ft
->encoding
.reverse_nibbles
== sox_option_default
)
332 ft
->encoding
.reverse_nibbles
= !!(ft
->handler
.flags
& SOX_FILE_NIB_REV
);
334 if (ft
->encoding
.reverse_nibbles
== !(ft
->handler
.flags
& SOX_FILE_NIB_REV
))
335 lsx_report("`%s': overriding file-type nibble-order", ft
->filename
);
338 static sox_bool
is_seekable(sox_format_t
const * ft
)
344 return !fseek(ft
->fp
, 0, SEEK_CUR
);
347 /* check that all settings have been given */
348 static int sox_checkformat(sox_format_t
* ft
)
350 ft
->sox_errno
= SOX_SUCCESS
;
352 if (ft
->signal
.rate
<= 0) {
353 lsx_fail_errno(ft
, SOX_EFMT
, "sample rate zero or negative");
356 if (!ft
->signal
.precision
) {
357 lsx_fail_errno(ft
,SOX_EFMT
,"data encoding or sample size was not specified");
363 static sox_bool
is_url(char const * text
) /* detects only wget-supported URLs */
366 strncasecmp(text
, "http:" , (size_t)5) &&
367 strncasecmp(text
, "https:", (size_t)6) &&
368 strncasecmp(text
, "ftp:" , (size_t)4));
371 static int xfclose(FILE * file
, lsx_io_type io_type
)
375 io_type
!= lsx_io_file
? pclose(file
) :
380 static void incr_pipe_size(FILE *f
)
383 * Linux 2.6.35 and later has the ability to expand the pipe buffer
384 * Try to get it as big as possible to avoid stalls when SoX itself
385 * is using big buffers
387 #if defined(F_GETPIPE_SZ) && defined(F_SETPIPE_SZ)
388 static long max_pipe_size
;
390 /* read the maximum size of the pipe the first time this is called */
391 if (max_pipe_size
== 0) {
392 const char path
[] = "/proc/sys/fs/pipe-max-size";
393 int fd
= open(path
, O_RDONLY
);
398 ssize_t r
= read(fd
, buf
, sizeof(buf
) - 1);
402 max_pipe_size
= strtol(buf
, NULL
, 10);
404 /* guard against obviously wrong values on messed up systems */
405 if (max_pipe_size
<= PIPE_BUF
|| max_pipe_size
> INT_MAX
)
412 if (max_pipe_size
> PIPE_BUF
) {
415 if (fcntl(fd
, F_SETPIPE_SZ
, max_pipe_size
) >= 0)
416 lsx_debug("got pipe %ld bytes\n", max_pipe_size
);
418 lsx_warn("couldn't set pipe size to %ld bytes: %s\n",
419 max_pipe_size
, strerror(errno
));
421 #endif /* do nothing for platforms without F_{GET,SET}PIPE_SZ */
424 static FILE * xfopen(char const * identifier
, char const * mode
, lsx_io_type
* io_type
)
426 *io_type
= lsx_io_file
;
428 if (*identifier
== '|') {
432 #define POPEN_MODE "r"
434 f
= popen(identifier
+ 1, POPEN_MODE
);
435 *io_type
= lsx_io_pipe
;
438 lsx_fail("this build of SoX cannot open pipes");
442 else if (is_url(identifier
)) {
445 char const * const command_format
= "wget --no-check-certificate -q -O- \"%s\"";
446 char * command
= lsx_malloc(strlen(command_format
) + strlen(identifier
));
447 sprintf(command
, command_format
, identifier
);
448 f
= popen(command
, POPEN_MODE
);
451 *io_type
= lsx_io_url
;
453 lsx_fail("this build of SoX cannot open URLs");
457 return fopen(identifier
, mode
);
460 /* Hack to rewind pipes (a small amount).
461 * Works by resetting the FILE buffer pointer */
462 static void UNUSED
rewind_pipe(FILE * fp
)
464 /* _FSTDIO is for Torek stdio (i.e. most BSD-derived libc's)
465 * In theory, we no longer need to check _NEWLIB_VERSION or __APPLE__ */
466 #if defined _FSTDIO || defined _NEWLIB_VERSION || defined __APPLE__
467 fp
->_p
-= PIPE_AUTO_DETECT_SIZE
;
468 fp
->_r
+= PIPE_AUTO_DETECT_SIZE
;
469 #elif defined __GLIBC__
470 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
471 #elif defined _MSC_VER && _MSC_VER >= 1900
472 #define NO_REWIND_PIPE
473 #elif defined _MSC_VER || defined _WIN32 || defined _WIN64 || \
474 defined _ISO_STDIO_ISO_H || defined __sgi
475 fp
->_ptr
= fp
->_base
;
477 /* To fix this #error, either simply remove the #error line and live without
478 * file-type detection with pipes, or add support for your compiler in the
479 * lines above. Test with cat monkey.wav | ./sox --info - */
480 #error FIX NEEDED HERE
481 #define NO_REWIND_PIPE
486 static sox_format_t
* open_read(
488 void * buffer UNUSED
,
489 size_t buffer_size UNUSED
,
490 sox_signalinfo_t
const * signal
,
491 sox_encodinginfo_t
const * encoding
,
492 char const * filetype
)
494 sox_format_t
* ft
= lsx_calloc(1, sizeof(*ft
));
495 sox_format_handler_t
const * handler
;
496 char const * const io_types
[] = {"file", "pipe", "file URL"};
497 char const * type
= "";
498 size_t input_bufsiz
= sox_globals
.input_bufsiz
?
499 sox_globals
.input_bufsiz
: sox_globals
.bufsiz
;
502 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
503 lsx_fail("no handler for given file type `%s'", filetype
);
506 ft
->handler
= *handler
;
509 if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
)) {
510 if (!strcmp(path
, "-")) { /* Use stdin if the filename is "-" */
511 if (sox_globals
.stdin_in_use_by
) {
512 lsx_fail("`-' (stdin) already in use by `%s'", sox_globals
.stdin_in_use_by
);
515 sox_globals
.stdin_in_use_by
= "audio input";
516 SET_BINARY_MODE(stdin
);
522 buffer
? fmemopen(buffer
, buffer_size
, "rb") :
524 xfopen(path
, "rb", &ft
->io_type
);
525 type
= io_types
[ft
->io_type
];
526 if (ft
->fp
== NULL
) {
527 lsx_fail("can't open input %s `%s': %s", type
, path
, strerror(errno
));
531 if (setvbuf (ft
->fp
, NULL
, _IOFBF
, sizeof(char) * input_bufsiz
)) {
532 lsx_fail("Can't set read buffer");
535 ft
->seekable
= is_seekable(ft
);
540 filetype
= auto_detect_format(ft
, lsx_find_file_extension(path
));
543 #ifndef NO_REWIND_PIPE
544 else if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
) &&
545 input_bufsiz
>= PIPE_AUTO_DETECT_SIZE
) {
546 filetype
= auto_detect_format(ft
, lsx_find_file_extension(path
));
553 lsx_report("detected file format type `%s'", filetype
);
554 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
555 lsx_fail("no handler for detected file type `%s'", filetype
);
560 if (ft
->io_type
== lsx_io_pipe
) {
561 filetype
= "sox"; /* With successful pipe rewind, this isn't useful */
562 lsx_report("assuming input pipe `%s' has file-type `sox'", path
);
564 else if (!(filetype
= lsx_find_file_extension(path
))) {
565 lsx_fail("can't determine type of %s `%s'", type
, path
);
568 if (!(handler
= sox_find_format(filetype
, sox_true
))) {
569 lsx_fail("no handler for file extension `%s'", filetype
);
573 ft
->handler
= *handler
;
574 if (ft
->handler
.flags
& SOX_FILE_NOSTDIO
) {
575 xfclose(ft
->fp
, ft
->io_type
);
579 if (!ft
->handler
.startread
&& !ft
->handler
.read
) {
580 lsx_fail("file type `%s' isn't readable", filetype
);
585 ft
->filetype
= lsx_strdup(filetype
);
586 ft
->filename
= lsx_strdup(path
);
588 ft
->signal
= *signal
;
591 ft
->encoding
= *encoding
;
592 else sox_init_encodinginfo(&ft
->encoding
);
593 set_endiannesses(ft
);
595 if ((ft
->handler
.flags
& SOX_FILE_DEVICE
) && !(ft
->handler
.flags
& SOX_FILE_PHONY
))
596 lsx_set_signal_defaults(ft
);
598 ft
->priv
= lsx_calloc(1, ft
->handler
.priv_size
);
599 /* Read and write starters can change their formats. */
600 if (ft
->handler
.startread
&& (*ft
->handler
.startread
)(ft
) != SOX_SUCCESS
) {
601 lsx_fail("can't open input %s `%s': %s", type
, ft
->filename
, ft
->sox_errstr
);
605 /* Fill in some defaults: */
606 if (sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
))
607 ft
->signal
.precision
= sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
);
608 if (!(ft
->handler
.flags
& SOX_FILE_PHONY
) && !ft
->signal
.channels
)
609 ft
->signal
.channels
= 1;
611 if (sox_checkformat(ft
) != SOX_SUCCESS
) {
612 lsx_fail("bad input format for %s `%s': %s", type
, ft
->filename
, ft
->sox_errstr
);
617 if (signal
->rate
&& signal
->rate
!= ft
->signal
.rate
)
618 lsx_warn("can't set sample rate %g; using %g", signal
->rate
, ft
->signal
.rate
);
619 if (signal
->channels
&& signal
->channels
!= ft
->signal
.channels
)
620 lsx_warn("can't set %u channels; using %u", signal
->channels
, ft
->signal
.channels
);
625 if (ft
->fp
&& ft
->fp
!= stdin
)
626 xfclose(ft
->fp
, ft
->io_type
);
634 sox_format_t
* sox_open_read(
636 sox_signalinfo_t
const * signal
,
637 sox_encodinginfo_t
const * encoding
,
638 char const * filetype
)
640 return open_read(path
, NULL
, (size_t)0, signal
, encoding
, filetype
);
643 sox_format_t
* sox_open_mem_read(
646 sox_signalinfo_t
const * signal
,
647 sox_encodinginfo_t
const * encoding
,
648 char const * filetype
)
650 return open_read("", buffer
, buffer_size
, signal
,encoding
,filetype
);
653 sox_bool
sox_format_supports_encoding(
655 char const * filetype
,
656 sox_encodinginfo_t
const * encoding
)
658 #define enc_arg(T) (T)handler->write_formats[i++]
659 sox_bool is_file_extension
= filetype
== NULL
;
660 sox_format_handler_t
const * handler
;
664 assert(path
|| filetype
);
667 filetype
= lsx_find_file_extension(path
);
669 if (!filetype
|| !(handler
= sox_find_format(filetype
, is_file_extension
)) ||
670 !handler
->write_formats
)
672 while ((e
= enc_arg(sox_encoding_t
))) {
673 if (e
== encoding
->encoding
) {
675 for (has_bits
= sox_false
; (s
= enc_arg(unsigned)); has_bits
= sox_true
)
676 if (s
== encoding
->bits_per_sample
)
678 if (!has_bits
&& !encoding
->bits_per_sample
)
682 while (enc_arg(unsigned));
688 static void set_output_format(sox_format_t
* ft
)
690 sox_encoding_t e
= SOX_ENCODING_UNKNOWN
;
692 unsigned const * encodings
= ft
->handler
.write_formats
;
693 #define enc_arg(T) (T)encodings[i++]
695 if (ft
->handler
.write_rates
){
696 if (!ft
->signal
.rate
)
697 ft
->signal
.rate
= ft
->handler
.write_rates
[0];
701 while ((r
= ft
->handler
.write_rates
[i
++])) {
702 if (r
== ft
->signal
.rate
)
705 if (r
!= ft
->signal
.rate
) {
706 sox_rate_t given
= ft
->signal
.rate
, max
= 0;
707 ft
->signal
.rate
= HUGE_VAL
;
709 while ((r
= ft
->handler
.write_rates
[i
++])) {
710 if (r
> given
&& r
< ft
->signal
.rate
)
712 else max
= max(r
, max
);
714 if (ft
->signal
.rate
== HUGE_VAL
)
715 ft
->signal
.rate
= max
;
716 lsx_warn("%s can't encode at %gHz; using %gHz", ft
->handler
.names
[0], given
, ft
->signal
.rate
);
720 else if (!ft
->signal
.rate
)
721 ft
->signal
.rate
= SOX_DEFAULT_RATE
;
723 if (ft
->handler
.flags
& SOX_FILE_CHANS
) {
724 if (ft
->signal
.channels
== 1 && !(ft
->handler
.flags
& SOX_FILE_MONO
)) {
725 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_STEREO
)? 2 : 4;
726 lsx_warn("%s can't encode mono; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
728 if (ft
->signal
.channels
== 2 && !(ft
->handler
.flags
& SOX_FILE_STEREO
)) {
729 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_QUAD
)? 4 : 1;
730 lsx_warn("%s can't encode stereo; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
732 if (ft
->signal
.channels
== 4 && !(ft
->handler
.flags
& SOX_FILE_QUAD
)) {
733 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_STEREO
)? 2 : 1;
734 lsx_warn("%s can't encode quad; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
736 } else ft
->signal
.channels
= max(ft
->signal
.channels
, 1);
740 /* If an encoding has been given, check if it supported by this handler */
741 if (ft
->encoding
.encoding
) {
743 while ((e
= enc_arg(sox_encoding_t
))) {
744 if (e
== ft
->encoding
.encoding
)
746 while (enc_arg(unsigned));
748 if (e
!= ft
->encoding
.encoding
) {
749 lsx_warn("%s can't encode %s", ft
->handler
.names
[0], sox_encodings_info
[ft
->encoding
.encoding
].desc
);
750 ft
->encoding
.encoding
= 0;
754 unsigned max_p_s
= 0;
755 unsigned given_size
= 0;
756 sox_bool found
= sox_false
;
757 if (ft
->encoding
.bits_per_sample
)
758 given_size
= ft
->encoding
.bits_per_sample
;
759 ft
->encoding
.bits_per_sample
= 65;
760 while ((s
= enc_arg(unsigned))) {
763 if (sox_precision(e
, s
) >= ft
->signal
.precision
) {
764 if (s
< ft
->encoding
.bits_per_sample
)
765 ft
->encoding
.bits_per_sample
= s
;
767 else if (sox_precision(e
, s
) > max_p
) {
768 max_p
= sox_precision(e
, s
);
772 if (ft
->encoding
.bits_per_sample
== 65)
773 ft
->encoding
.bits_per_sample
= max_p_s
;
776 ft
->encoding
.bits_per_sample
= given_size
;
777 else lsx_warn("%s can't encode %s to %u-bit", ft
->handler
.names
[0], sox_encodings_info
[ft
->encoding
.encoding
].desc
, given_size
);
782 /* If a size has been given, check if it supported by this handler */
783 if (!ft
->encoding
.encoding
&& ft
->encoding
.bits_per_sample
) {
786 while (s
!= ft
->encoding
.bits_per_sample
&& (e
= enc_arg(sox_encoding_t
)))
787 while ((s
= enc_arg(unsigned)) && s
!= ft
->encoding
.bits_per_sample
);
788 if (s
!= ft
->encoding
.bits_per_sample
) {
789 lsx_warn("%s can't encode to %u-bit", ft
->handler
.names
[0], ft
->encoding
.bits_per_sample
);
790 ft
->encoding
.bits_per_sample
= 0;
792 else ft
->encoding
.encoding
= e
;
795 /* Find the smallest lossless encoding with precision >= signal.precision */
796 if (!ft
->encoding
.encoding
) {
797 ft
->encoding
.bits_per_sample
= 65;
799 while ((e
= enc_arg(sox_encoding_t
)))
800 while ((s
= enc_arg(unsigned)))
801 if (!(sox_encodings_info
[e
].flags
& (sox_encodings_lossy1
| sox_encodings_lossy2
)) &&
802 sox_precision(e
, s
) >= ft
->signal
.precision
&& s
< ft
->encoding
.bits_per_sample
) {
803 ft
->encoding
.encoding
= e
;
804 ft
->encoding
.bits_per_sample
= s
;
808 /* Find the smallest lossy encoding with precision >= signal precision,
809 * or, if none such, the highest precision encoding */
810 if (!ft
->encoding
.encoding
) {
812 sox_encoding_t max_p_e
= 0;
813 unsigned max_p_s
= 0;
815 while ((e
= enc_arg(sox_encoding_t
)))
817 s
= enc_arg(unsigned);
818 if (sox_precision(e
, s
) >= ft
->signal
.precision
) {
819 if (s
< ft
->encoding
.bits_per_sample
) {
820 ft
->encoding
.encoding
= e
;
821 ft
->encoding
.bits_per_sample
= s
;
824 else if (sox_precision(e
, s
) > max_p
) {
825 max_p
= sox_precision(e
, s
);
830 if (!ft
->encoding
.encoding
) {
831 ft
->encoding
.encoding
= max_p_e
;
832 ft
->encoding
.bits_per_sample
= max_p_s
;
835 ft
->signal
.precision
= sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
);
839 sox_format_handler_t
const * sox_write_handler(
841 char const * filetype
,
842 char const * * filetype1
)
844 sox_format_handler_t
const * handler
;
846 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
848 lsx_fail("no handler for given file type `%s'", filetype
);
853 if (!(filetype
= lsx_find_file_extension(path
))) {
855 lsx_fail("can't determine type of `%s'", path
);
858 if (!(handler
= sox_find_format(filetype
, sox_true
))) {
860 lsx_fail("no handler for file extension `%s'", filetype
);
865 if (!handler
->startwrite
&& !handler
->write
) {
867 lsx_fail("file type `%s' isn't writable", filetype
);
871 *filetype1
= filetype
;
875 static sox_format_t
* open_write(
877 void * buffer UNUSED
,
878 size_t buffer_size UNUSED
,
879 char * * buffer_ptr UNUSED
,
880 size_t * buffer_size_ptr UNUSED
,
881 sox_signalinfo_t
const * signal
,
882 sox_encodinginfo_t
const * encoding
,
883 char const * filetype
,
884 sox_oob_t
const * oob
,
885 sox_bool (*overwrite_permitted
)(const char *filename
))
887 sox_format_t
* ft
= lsx_calloc(sizeof(*ft
), 1);
888 sox_format_handler_t
const * handler
;
890 if (!path
|| !signal
) {
891 lsx_fail("must specify file name and signal parameters to write file");
895 if (!(handler
= sox_write_handler(path
, filetype
, &filetype
)))
898 ft
->handler
= *handler
;
900 if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
)) {
901 if (!strcmp(path
, "-")) { /* Use stdout if the filename is "-" */
902 if (sox_globals
.stdout_in_use_by
) {
903 lsx_fail("`-' (stdout) already in use by `%s'", sox_globals
.stdout_in_use_by
);
906 sox_globals
.stdout_in_use_by
= "audio output";
907 SET_BINARY_MODE(stdout
);
912 if (!stat(path
, &st
) && (st
.st_mode
& S_IFMT
) == S_IFREG
&&
913 (overwrite_permitted
&& !overwrite_permitted(path
))) {
914 lsx_fail("permission to overwrite `%s' denied", path
);
919 buffer
? fmemopen(buffer
, buffer_size
, "w+b") :
920 buffer_ptr
? open_memstream(buffer_ptr
, buffer_size_ptr
) :
923 if (ft
->fp
== NULL
) {
924 lsx_fail("can't open output file `%s': %s", path
, strerror(errno
));
929 /* stdout tends to be line-buffered. Override this */
930 /* to be Full Buffering. */
931 if (setvbuf (ft
->fp
, NULL
, _IOFBF
, sizeof(char) * sox_globals
.bufsiz
)) {
932 lsx_fail("Can't set write buffer");
935 ft
->seekable
= is_seekable(ft
);
938 ft
->filetype
= lsx_strdup(filetype
);
939 ft
->filename
= lsx_strdup(path
);
941 ft
->signal
= *signal
;
944 ft
->encoding
= *encoding
;
945 else sox_init_encodinginfo(&ft
->encoding
);
946 set_endiannesses(ft
);
951 ft
->oob
.comments
= sox_copy_comments(oob
->comments
);
954 set_output_format(ft
);
956 /* FIXME: doesn't cover the situation where
957 * codec changes audio length due to block alignment (e.g. 8svx, gsm): */
958 if (signal
->rate
&& signal
->channels
)
959 ft
->signal
.length
= ft
->signal
.length
* ft
->signal
.rate
/ signal
->rate
*
960 ft
->signal
.channels
/ signal
->channels
+ .5;
962 if ((ft
->handler
.flags
& SOX_FILE_REWIND
) && strcmp(ft
->filetype
, "sox") && !ft
->signal
.length
&& !ft
->seekable
)
963 lsx_warn("can't seek in output file `%s'; length in file header will be unspecified", ft
->filename
);
965 ft
->priv
= lsx_calloc(1, ft
->handler
.priv_size
);
966 /* Read and write starters can change their formats. */
967 if (ft
->handler
.startwrite
&& (ft
->handler
.startwrite
)(ft
) != SOX_SUCCESS
){
968 lsx_fail("can't open output file `%s': %s", ft
->filename
, ft
->sox_errstr
);
972 if (sox_checkformat(ft
) != SOX_SUCCESS
) {
973 lsx_fail("bad format for output file `%s': %s", ft
->filename
, ft
->sox_errstr
);
977 if ((ft
->handler
.flags
& SOX_FILE_DEVICE
) && signal
) {
978 if (signal
->rate
&& signal
->rate
!= ft
->signal
.rate
)
979 lsx_report("can't set sample rate %g; using %g", signal
->rate
, ft
->signal
.rate
);
980 if (signal
->channels
&& signal
->channels
!= ft
->signal
.channels
)
981 lsx_report("can't set %u channels; using %u", signal
->channels
, ft
->signal
.channels
);
986 if (ft
->fp
&& ft
->fp
!= stdout
)
987 xfclose(ft
->fp
, ft
->io_type
);
995 sox_format_t
* sox_open_write(
997 sox_signalinfo_t
const * signal
,
998 sox_encodinginfo_t
const * encoding
,
999 char const * filetype
,
1000 sox_oob_t
const * oob
,
1001 sox_bool (*overwrite_permitted
)(const char *filename
))
1003 return open_write(path
, NULL
, (size_t)0, NULL
, NULL
, signal
, encoding
, filetype
, oob
, overwrite_permitted
);
1006 sox_format_t
* sox_open_mem_write(
1009 sox_signalinfo_t
const * signal
,
1010 sox_encodinginfo_t
const * encoding
,
1011 char const * filetype
,
1012 sox_oob_t
const * oob
)
1014 return open_write("", buffer
, buffer_size
, NULL
, NULL
, signal
, encoding
, filetype
, oob
, NULL
);
1017 sox_format_t
* sox_open_memstream_write(
1018 char * * buffer_ptr
,
1019 size_t * buffer_size_ptr
,
1020 sox_signalinfo_t
const * signal
,
1021 sox_encodinginfo_t
const * encoding
,
1022 char const * filetype
,
1023 sox_oob_t
const * oob
)
1025 return open_write("", NULL
, (size_t)0, buffer_ptr
, buffer_size_ptr
, signal
, encoding
, filetype
, oob
, NULL
);
1028 size_t sox_read(sox_format_t
* ft
, sox_sample_t
* buf
, size_t len
)
1031 if (ft
->signal
.length
!= SOX_UNSPEC
)
1032 len
= min(len
, ft
->signal
.length
- ft
->olength
);
1033 actual
= ft
->handler
.read
? (*ft
->handler
.read
)(ft
, buf
, len
) : 0;
1034 actual
= actual
> len
? 0 : actual
;
1035 ft
->olength
+= actual
;
1039 size_t sox_write(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t len
)
1041 size_t actual
= ft
->handler
.write
? (*ft
->handler
.write
)(ft
, buf
, len
) : 0;
1042 ft
->olength
+= actual
;
1046 int sox_close(sox_format_t
* ft
)
1048 int result
= SOX_SUCCESS
;
1050 if (ft
->mode
== 'r')
1051 result
= ft
->handler
.stopread
? (*ft
->handler
.stopread
)(ft
) : SOX_SUCCESS
;
1053 if (ft
->handler
.flags
& SOX_FILE_REWIND
) {
1054 if (ft
->olength
!= ft
->signal
.length
&& ft
->seekable
) {
1055 result
= lsx_seeki(ft
, (off_t
)0, 0);
1056 if (result
== SOX_SUCCESS
)
1057 result
= ft
->handler
.stopwrite
? (*ft
->handler
.stopwrite
)(ft
)
1058 : ft
->handler
.startwrite
?(*ft
->handler
.startwrite
)(ft
) : SOX_SUCCESS
;
1061 else result
= ft
->handler
.stopwrite
? (*ft
->handler
.stopwrite
)(ft
) : SOX_SUCCESS
;
1064 if (ft
->fp
== stdin
) {
1065 sox_globals
.stdin_in_use_by
= NULL
;
1066 } else if (ft
->fp
== stdout
) {
1068 sox_globals
.stdout_in_use_by
= NULL
;
1069 } else if (ft
->fp
) {
1070 xfclose(ft
->fp
, ft
->io_type
);
1076 sox_delete_comments(&ft
->oob
.comments
);
1082 int sox_seek(sox_format_t
* ft
, sox_uint64_t offset
, int whence
)
1084 /* FIXME: Implement SOX_SEEK_CUR and SOX_SEEK_END. */
1085 if (whence
!= SOX_SEEK_SET
)
1086 return SOX_EOF
; /* FIXME: return SOX_EINVAL */
1088 /* If file is a seekable file and this handler supports seeking,
1089 * then invoke handler's function.
1091 if (ft
->seekable
&& ft
->handler
.seek
)
1092 return (*ft
->handler
.seek
)(ft
, offset
);
1093 return SOX_EOF
; /* FIXME: return SOX_EBADF */
1096 static int strcaseends(char const * str
, char const * end
)
1098 size_t str_len
= strlen(str
), end_len
= strlen(end
);
1099 return str_len
>= end_len
&& !strcasecmp(str
+ str_len
- end_len
, end
);
1102 typedef enum {None
, M3u
, Pls
} playlist_t
;
1104 static playlist_t
playlist_type(char const * filename
)
1107 playlist_t result
= None
;
1109 if (*filename
== '|')
1111 if (strcaseends(filename
, ".m3u"))
1113 if (strcaseends(filename
, ".pls"))
1115 x
= lsx_strdup(filename
);
1116 p
= strrchr(x
, '?');
1119 result
= playlist_type(x
);
1125 sox_bool
sox_is_playlist(char const * filename
)
1127 return playlist_type(filename
) != None
;
1130 int sox_parse_playlist(sox_playlist_callback_t callback
, void * p
, char const * const listname
)
1132 sox_bool
const is_pls
= playlist_type(listname
) == Pls
;
1133 int const comment_char
= "#;"[is_pls
];
1134 size_t text_length
= 100;
1135 char * text
= lsx_malloc(text_length
+ 1);
1136 char * dirname
= lsx_strdup(listname
);
1137 char * slash_pos
= LAST_SLASH(dirname
);
1138 lsx_io_type io_type
;
1139 FILE * file
= xfopen(listname
, "r", &io_type
);
1141 int c
, result
= SOX_SUCCESS
;
1149 lsx_fail("Can't open playlist file `%s': %s", listname
, strerror(errno
));
1155 size_t begin
= 0, end
= 0;
1157 while (isspace(c
= getc(file
)));
1160 while (c
!= EOF
&& !strchr("\r\n", c
) && c
!= comment_char
) {
1161 if (i
== text_length
)
1162 text
= lsx_realloc(text
, (text_length
<<= 1) + 1);
1164 if (!strchr(" \t\f", c
))
1170 if (c
== comment_char
) {
1172 while (c
!= EOF
&& !strchr("\r\n", c
));
1179 if (!strncasecmp(text
, "file", (size_t) 4) && sscanf(text
+ 4, "%*u=%c", &dummy
) == 1)
1180 begin
= strchr(text
+ 5, '=') - text
+ 1;
1184 char const * id
= text
+ begin
;
1186 if (!dirname
[0] || is_url(id
) || IS_ABSOLUTE(id
))
1187 filename
= lsx_strdup(id
);
1189 filename
= lsx_malloc(strlen(dirname
) + strlen(id
) + 2);
1190 sprintf(filename
, "%s/%s", dirname
, id
);
1192 if (sox_is_playlist(filename
))
1193 sox_parse_playlist(callback
, p
, filename
);
1194 else if (callback(p
, filename
))
1201 lsx_fail("error reading playlist file `%s': %s", listname
, strerror(errno
));
1204 if (xfclose(file
, io_type
) && io_type
== lsx_io_url
) {
1205 lsx_fail("error reading playlist file URL `%s'", listname
);
1214 /*----------------------------- Formats library ------------------------------*/
1217 #define FORMAT(f) f,
1218 #include "formats.h"
1223 static sox_bool plugins_initted
= sox_false
;
1225 #ifdef HAVE_LIBLTDL /* Plugin format handlers */
1226 #define MAX_DYNAMIC_FORMATS 42
1227 #define MAX_FORMATS (NSTATIC_FORMATS + MAX_DYNAMIC_FORMATS)
1228 #define MAX_FORMATS_1 (MAX_FORMATS + 1)
1229 #define MAX_NAME_LEN (size_t)1024 /* FIXME: Use vasprintf */
1231 #define MAX_FORMATS_1
1234 #define FORMAT(f) extern sox_format_handler_t const * lsx_##f##_format_fn(void);
1235 #include "formats.h"
1238 static sox_format_tab_t s_sox_format_fns
[MAX_FORMATS_1
] = {
1239 #define FORMAT(f) {NULL, lsx_##f##_format_fn},
1240 #include "formats.h"
1245 const sox_format_tab_t
*
1246 sox_get_format_fns(void)
1248 return s_sox_format_fns
;
1251 static unsigned nformats
= NSTATIC_FORMATS
;
1253 #ifdef HAVE_LIBLTDL /* Plugin format handlers */
1255 static int init_format(const char *file
, lt_ptr data
)
1257 lt_dlhandle lth
= lt_dlopenext(file
);
1258 const char *end
= file
+ strlen(file
);
1259 const char prefix
[] = "sox_fmt_";
1260 char fnname
[MAX_NAME_LEN
];
1261 char *start
= strstr(file
, prefix
);
1264 if (start
&& (start
+= sizeof(prefix
) - 1) < end
) {
1265 int ret
= snprintf(fnname
, MAX_NAME_LEN
,
1266 "lsx_%.*s_format_fn", (int)(end
- start
), start
);
1267 if (ret
> 0 && ret
< (int)MAX_NAME_LEN
) {
1268 union {sox_format_fn_t fn
; lt_ptr ptr
;} ltptr
;
1269 ltptr
.ptr
= lt_dlsym(lth
, fnname
);
1270 lsx_debug("opening format plugin `%s': library %p, entry point %p\n",
1271 fnname
, (void *)lth
, ltptr
.ptr
);
1272 if (ltptr
.fn
&& (ltptr
.fn()->sox_lib_version_code
& ~255) ==
1273 (SOX_LIB_VERSION_CODE
& ~255)) { /* compatible version check */
1274 if (nformats
== MAX_FORMATS
) {
1275 lsx_warn("too many plugin formats");
1278 s_sox_format_fns
[nformats
++].fn
= ltptr
.fn
;
1286 int sox_format_init(void) /* Find & load format handlers. */
1288 if (plugins_initted
)
1291 plugins_initted
= sox_true
;
1294 int error
= lt_dlinit();
1296 lsx_fail("lt_dlinit failed with %d error(s): %s", error
, lt_dlerror());
1299 lt_dlforeachfile(PKGLIBDIR
, init_format
, NULL
);
1305 void sox_format_quit(void) /* Cleanup things. */
1309 if (plugins_initted
&& (ret
= lt_dlexit()) != 0)
1310 lsx_fail("lt_dlexit failed with %d error(s): %s", ret
, lt_dlerror());
1311 plugins_initted
= sox_false
;
1312 nformats
= NSTATIC_FORMATS
;
1316 /* Find a named format in the formats library.
1318 * (c) 2005-9 Chris Bagwell and SoX contributors.
1319 * Copyright 1991 Lance Norskog And Sundry Contributors.
1321 * This source code is freely redistributable and may be used for any
1322 * purpose. This copyright notice must be maintained.
1324 * Lance Norskog, Sundry Contributors, Chris Bagwell and SoX contributors
1325 * are not responsible for the consequences of using this software.
1327 sox_format_handler_t
const * sox_find_format(char const * name0
, sox_bool no_dev
)
1332 char * name
= lsx_strdup(name0
);
1333 char * pos
= strchr(name
, ';');
1334 if (pos
) /* Use only the 1st clause of a mime string */
1336 for (f
= 0; f
< nformats
; ++f
) {
1337 sox_format_handler_t
const * handler
= s_sox_format_fns
[f
].fn();
1339 if (!(no_dev
&& (handler
->flags
& SOX_FILE_DEVICE
)))
1340 for (n
= 0; handler
->names
[n
]; ++n
)
1341 if (!strcasecmp(handler
->names
[n
], name
)) {
1343 return handler
; /* Found it. */
1348 if (sox_format_init() == SOX_SUCCESS
) /* Try again with plugins */
1349 return sox_find_format(name0
, no_dev
);