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
->encoding
.opposite_endian
)
306 ft
->encoding
.reverse_bytes
= (ft
->handler
.flags
& SOX_FILE_ENDIAN
)?
307 !(ft
->handler
.flags
& SOX_FILE_ENDBIG
) != MACHINE_IS_BIGENDIAN
: sox_true
;
308 else if (ft
->encoding
.reverse_bytes
== sox_option_default
)
309 ft
->encoding
.reverse_bytes
= (ft
->handler
.flags
& SOX_FILE_ENDIAN
)?
310 !(ft
->handler
.flags
& SOX_FILE_ENDBIG
) == MACHINE_IS_BIGENDIAN
: sox_false
;
312 /* FIXME: Change reports to suitable warnings if trying
313 * to override something that can't be overridden. */
315 if (ft
->handler
.flags
& SOX_FILE_ENDIAN
) {
316 if (ft
->encoding
.reverse_bytes
== (sox_option_t
)
317 (!(ft
->handler
.flags
& SOX_FILE_ENDBIG
) != MACHINE_IS_BIGENDIAN
))
318 lsx_report("`%s': overriding file-type byte-order", ft
->filename
);
319 } else if (ft
->encoding
.reverse_bytes
== sox_option_yes
)
320 lsx_report("`%s': overriding machine byte-order", ft
->filename
);
322 if (ft
->encoding
.reverse_bits
== sox_option_default
)
323 ft
->encoding
.reverse_bits
= !!(ft
->handler
.flags
& SOX_FILE_BIT_REV
);
324 else if (ft
->encoding
.reverse_bits
== !(ft
->handler
.flags
& SOX_FILE_BIT_REV
))
325 lsx_report("`%s': overriding file-type bit-order", ft
->filename
);
327 if (ft
->encoding
.reverse_nibbles
== sox_option_default
)
328 ft
->encoding
.reverse_nibbles
= !!(ft
->handler
.flags
& SOX_FILE_NIB_REV
);
330 if (ft
->encoding
.reverse_nibbles
== !(ft
->handler
.flags
& SOX_FILE_NIB_REV
))
331 lsx_report("`%s': overriding file-type nibble-order", ft
->filename
);
334 static sox_bool
is_seekable(sox_format_t
const * ft
)
340 return !fseek(ft
->fp
, 0, SEEK_CUR
);
343 /* check that all settings have been given */
344 static int sox_checkformat(sox_format_t
* ft
)
346 ft
->sox_errno
= SOX_SUCCESS
;
348 if (ft
->signal
.rate
<= 0) {
349 lsx_fail_errno(ft
, SOX_EFMT
, "sample rate zero or negative");
352 if (!ft
->signal
.precision
) {
353 lsx_fail_errno(ft
,SOX_EFMT
,"data encoding or sample size was not specified");
359 static sox_bool
is_url(char const * text
) /* detects only wget-supported URLs */
362 strncasecmp(text
, "http:" , (size_t)5) &&
363 strncasecmp(text
, "https:", (size_t)6) &&
364 strncasecmp(text
, "ftp:" , (size_t)4));
367 static int xfclose(FILE * file
, lsx_io_type io_type
)
371 io_type
!= lsx_io_file
? pclose(file
) :
376 static void incr_pipe_size(FILE *f
)
379 * Linux 2.6.35 and later has the ability to expand the pipe buffer
380 * Try to get it as big as possible to avoid stalls when SoX itself
381 * is using big buffers
383 #if defined(F_GETPIPE_SZ) && defined(F_SETPIPE_SZ)
384 static long max_pipe_size
;
386 /* read the maximum size of the pipe the first time this is called */
387 if (max_pipe_size
== 0) {
388 const char path
[] = "/proc/sys/fs/pipe-max-size";
389 int fd
= open(path
, O_RDONLY
);
394 ssize_t r
= read(fd
, buf
, sizeof(buf
) - 1);
398 max_pipe_size
= strtol(buf
, NULL
, 10);
400 /* guard against obviously wrong values on messed up systems */
401 if (max_pipe_size
<= PIPE_BUF
|| max_pipe_size
> INT_MAX
)
408 if (max_pipe_size
> PIPE_BUF
) {
411 if (fcntl(fd
, F_SETPIPE_SZ
, max_pipe_size
) >= 0)
412 lsx_debug("got pipe %ld bytes\n", max_pipe_size
);
414 lsx_warn("couldn't set pipe size to %ld bytes: %s\n",
415 max_pipe_size
, strerror(errno
));
417 #endif /* do nothing for platforms without F_{GET,SET}PIPE_SZ */
420 static FILE * xfopen(char const * identifier
, char const * mode
, lsx_io_type
* io_type
)
422 *io_type
= lsx_io_file
;
424 if (*identifier
== '|') {
428 #define POPEN_MODE "r"
430 f
= popen(identifier
+ 1, POPEN_MODE
);
431 *io_type
= lsx_io_pipe
;
434 lsx_fail("this build of SoX cannot open pipes");
438 else if (is_url(identifier
)) {
441 char const * const command_format
= "wget --no-check-certificate -q -O- \"%s\"";
442 char * command
= lsx_malloc(strlen(command_format
) + strlen(identifier
));
443 sprintf(command
, command_format
, identifier
);
444 f
= popen(command
, POPEN_MODE
);
447 *io_type
= lsx_io_url
;
449 lsx_fail("this build of SoX cannot open URLs");
453 return fopen(identifier
, mode
);
456 /* Hack to rewind pipes (a small amount).
457 * Works by resetting the FILE buffer pointer */
458 static void UNUSED
rewind_pipe(FILE * fp
)
460 /* _FSTDIO is for Torek stdio (i.e. most BSD-derived libc's)
461 * In theory, we no longer need to check _NEWLIB_VERSION or __APPLE__ */
462 #if defined _FSTDIO || defined _NEWLIB_VERSION || defined __APPLE__
463 fp
->_p
-= PIPE_AUTO_DETECT_SIZE
;
464 fp
->_r
+= PIPE_AUTO_DETECT_SIZE
;
465 #elif defined __GLIBC__
466 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
467 #elif defined _MSC_VER && _MSC_VER >= 1900
468 #define NO_REWIND_PIPE
469 #elif defined _MSC_VER || defined _WIN32 || defined _WIN64 || \
470 defined _ISO_STDIO_ISO_H || defined __sgi
471 fp
->_ptr
= fp
->_base
;
473 /* To fix this #error, either simply remove the #error line and live without
474 * file-type detection with pipes, or add support for your compiler in the
475 * lines above. Test with cat monkey.wav | ./sox --info - */
476 #error FIX NEEDED HERE
477 #define NO_REWIND_PIPE
482 static sox_format_t
* open_read(
484 void * buffer UNUSED
,
485 size_t buffer_size UNUSED
,
486 sox_signalinfo_t
const * signal
,
487 sox_encodinginfo_t
const * encoding
,
488 char const * filetype
)
490 sox_format_t
* ft
= lsx_calloc(1, sizeof(*ft
));
491 sox_format_handler_t
const * handler
;
492 char const * const io_types
[] = {"file", "pipe", "file URL"};
493 char const * type
= "";
494 size_t input_bufsiz
= sox_globals
.input_bufsiz
?
495 sox_globals
.input_bufsiz
: sox_globals
.bufsiz
;
498 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
499 lsx_fail("no handler for given file type `%s'", filetype
);
502 ft
->handler
= *handler
;
505 if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
)) {
506 if (!strcmp(path
, "-")) { /* Use stdin if the filename is "-" */
507 if (sox_globals
.stdin_in_use_by
) {
508 lsx_fail("`-' (stdin) already in use by `%s'", sox_globals
.stdin_in_use_by
);
511 sox_globals
.stdin_in_use_by
= "audio input";
512 SET_BINARY_MODE(stdin
);
518 buffer
? fmemopen(buffer
, buffer_size
, "rb") :
520 xfopen(path
, "rb", &ft
->io_type
);
521 type
= io_types
[ft
->io_type
];
522 if (ft
->fp
== NULL
) {
523 lsx_fail("can't open input %s `%s': %s", type
, path
, strerror(errno
));
527 if (setvbuf (ft
->fp
, NULL
, _IOFBF
, sizeof(char) * input_bufsiz
)) {
528 lsx_fail("Can't set read buffer");
531 ft
->seekable
= is_seekable(ft
);
536 filetype
= auto_detect_format(ft
, lsx_find_file_extension(path
));
539 #ifndef NO_REWIND_PIPE
540 else if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
) &&
541 input_bufsiz
>= PIPE_AUTO_DETECT_SIZE
) {
542 filetype
= auto_detect_format(ft
, lsx_find_file_extension(path
));
549 lsx_report("detected file format type `%s'", filetype
);
550 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
551 lsx_fail("no handler for detected file type `%s'", filetype
);
556 if (ft
->io_type
== lsx_io_pipe
) {
557 filetype
= "sox"; /* With successful pipe rewind, this isn't useful */
558 lsx_report("assuming input pipe `%s' has file-type `sox'", path
);
560 else if (!(filetype
= lsx_find_file_extension(path
))) {
561 lsx_fail("can't determine type of %s `%s'", type
, path
);
564 if (!(handler
= sox_find_format(filetype
, sox_true
))) {
565 lsx_fail("no handler for file extension `%s'", filetype
);
569 ft
->handler
= *handler
;
570 if (ft
->handler
.flags
& SOX_FILE_NOSTDIO
) {
571 xfclose(ft
->fp
, ft
->io_type
);
575 if (!ft
->handler
.startread
&& !ft
->handler
.read
) {
576 lsx_fail("file type `%s' isn't readable", filetype
);
581 ft
->filetype
= lsx_strdup(filetype
);
582 ft
->filename
= lsx_strdup(path
);
584 ft
->signal
= *signal
;
587 ft
->encoding
= *encoding
;
588 else sox_init_encodinginfo(&ft
->encoding
);
589 set_endiannesses(ft
);
591 if ((ft
->handler
.flags
& SOX_FILE_DEVICE
) && !(ft
->handler
.flags
& SOX_FILE_PHONY
))
592 lsx_set_signal_defaults(ft
);
594 ft
->priv
= lsx_calloc(1, ft
->handler
.priv_size
);
595 /* Read and write starters can change their formats. */
596 if (ft
->handler
.startread
&& (*ft
->handler
.startread
)(ft
) != SOX_SUCCESS
) {
597 lsx_fail("can't open input %s `%s': %s", type
, ft
->filename
, ft
->sox_errstr
);
601 /* Fill in some defaults: */
602 if (sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
))
603 ft
->signal
.precision
= sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
);
604 if (!(ft
->handler
.flags
& SOX_FILE_PHONY
) && !ft
->signal
.channels
)
605 ft
->signal
.channels
= 1;
607 if (sox_checkformat(ft
) != SOX_SUCCESS
) {
608 lsx_fail("bad input format for %s `%s': %s", type
, ft
->filename
, ft
->sox_errstr
);
613 if (signal
->rate
&& signal
->rate
!= ft
->signal
.rate
)
614 lsx_warn("can't set sample rate %g; using %g", signal
->rate
, ft
->signal
.rate
);
615 if (signal
->channels
&& signal
->channels
!= ft
->signal
.channels
)
616 lsx_warn("can't set %u channels; using %u", signal
->channels
, ft
->signal
.channels
);
621 if (ft
->fp
&& ft
->fp
!= stdin
)
622 xfclose(ft
->fp
, ft
->io_type
);
630 sox_format_t
* sox_open_read(
632 sox_signalinfo_t
const * signal
,
633 sox_encodinginfo_t
const * encoding
,
634 char const * filetype
)
636 return open_read(path
, NULL
, (size_t)0, signal
, encoding
, filetype
);
639 sox_format_t
* sox_open_mem_read(
642 sox_signalinfo_t
const * signal
,
643 sox_encodinginfo_t
const * encoding
,
644 char const * filetype
)
646 return open_read("", buffer
, buffer_size
, signal
,encoding
,filetype
);
649 sox_bool
sox_format_supports_encoding(
651 char const * filetype
,
652 sox_encodinginfo_t
const * encoding
)
654 #define enc_arg(T) (T)handler->write_formats[i++]
655 sox_bool is_file_extension
= filetype
== NULL
;
656 sox_format_handler_t
const * handler
;
660 assert(path
|| filetype
);
663 filetype
= lsx_find_file_extension(path
);
665 if (!filetype
|| !(handler
= sox_find_format(filetype
, is_file_extension
)) ||
666 !handler
->write_formats
)
668 while ((e
= enc_arg(sox_encoding_t
))) {
669 if (e
== encoding
->encoding
) {
671 for (has_bits
= sox_false
; (s
= enc_arg(unsigned)); has_bits
= sox_true
)
672 if (s
== encoding
->bits_per_sample
)
674 if (!has_bits
&& !encoding
->bits_per_sample
)
678 while (enc_arg(unsigned));
684 static void set_output_format(sox_format_t
* ft
)
686 sox_encoding_t e
= SOX_ENCODING_UNKNOWN
;
688 unsigned const * encodings
= ft
->handler
.write_formats
;
689 #define enc_arg(T) (T)encodings[i++]
691 if (ft
->handler
.write_rates
){
692 if (!ft
->signal
.rate
)
693 ft
->signal
.rate
= ft
->handler
.write_rates
[0];
697 while ((r
= ft
->handler
.write_rates
[i
++])) {
698 if (r
== ft
->signal
.rate
)
701 if (r
!= ft
->signal
.rate
) {
702 sox_rate_t given
= ft
->signal
.rate
, max
= 0;
703 ft
->signal
.rate
= HUGE_VAL
;
705 while ((r
= ft
->handler
.write_rates
[i
++])) {
706 if (r
> given
&& r
< ft
->signal
.rate
)
708 else max
= max(r
, max
);
710 if (ft
->signal
.rate
== HUGE_VAL
)
711 ft
->signal
.rate
= max
;
712 lsx_warn("%s can't encode at %gHz; using %gHz", ft
->handler
.names
[0], given
, ft
->signal
.rate
);
716 else if (!ft
->signal
.rate
)
717 ft
->signal
.rate
= SOX_DEFAULT_RATE
;
719 if (ft
->handler
.flags
& SOX_FILE_CHANS
) {
720 if (ft
->signal
.channels
== 1 && !(ft
->handler
.flags
& SOX_FILE_MONO
)) {
721 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_STEREO
)? 2 : 4;
722 lsx_warn("%s can't encode mono; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
724 if (ft
->signal
.channels
== 2 && !(ft
->handler
.flags
& SOX_FILE_STEREO
)) {
725 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_QUAD
)? 4 : 1;
726 lsx_warn("%s can't encode stereo; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
728 if (ft
->signal
.channels
== 4 && !(ft
->handler
.flags
& SOX_FILE_QUAD
)) {
729 ft
->signal
.channels
= (ft
->handler
.flags
& SOX_FILE_STEREO
)? 2 : 1;
730 lsx_warn("%s can't encode quad; setting channels to %u", ft
->handler
.names
[0], ft
->signal
.channels
);
732 } else ft
->signal
.channels
= max(ft
->signal
.channels
, 1);
736 /* If an encoding has been given, check if it supported by this handler */
737 if (ft
->encoding
.encoding
) {
739 while ((e
= enc_arg(sox_encoding_t
))) {
740 if (e
== ft
->encoding
.encoding
)
742 while (enc_arg(unsigned));
744 if (e
!= ft
->encoding
.encoding
) {
745 lsx_warn("%s can't encode %s", ft
->handler
.names
[0], sox_encodings_info
[ft
->encoding
.encoding
].desc
);
746 ft
->encoding
.encoding
= 0;
750 unsigned max_p_s
= 0;
751 unsigned given_size
= 0;
752 sox_bool found
= sox_false
;
753 if (ft
->encoding
.bits_per_sample
)
754 given_size
= ft
->encoding
.bits_per_sample
;
755 ft
->encoding
.bits_per_sample
= 65;
756 while ((s
= enc_arg(unsigned))) {
759 if (sox_precision(e
, s
) >= ft
->signal
.precision
) {
760 if (s
< ft
->encoding
.bits_per_sample
)
761 ft
->encoding
.bits_per_sample
= s
;
763 else if (sox_precision(e
, s
) > max_p
) {
764 max_p
= sox_precision(e
, s
);
768 if (ft
->encoding
.bits_per_sample
== 65)
769 ft
->encoding
.bits_per_sample
= max_p_s
;
772 ft
->encoding
.bits_per_sample
= given_size
;
773 else lsx_warn("%s can't encode %s to %u-bit", ft
->handler
.names
[0], sox_encodings_info
[ft
->encoding
.encoding
].desc
, given_size
);
778 /* If a size has been given, check if it supported by this handler */
779 if (!ft
->encoding
.encoding
&& ft
->encoding
.bits_per_sample
) {
782 while (s
!= ft
->encoding
.bits_per_sample
&& (e
= enc_arg(sox_encoding_t
)))
783 while ((s
= enc_arg(unsigned)) && s
!= ft
->encoding
.bits_per_sample
);
784 if (s
!= ft
->encoding
.bits_per_sample
) {
785 lsx_warn("%s can't encode to %u-bit", ft
->handler
.names
[0], ft
->encoding
.bits_per_sample
);
786 ft
->encoding
.bits_per_sample
= 0;
788 else ft
->encoding
.encoding
= e
;
791 /* Find the smallest lossless encoding with precision >= signal.precision */
792 if (!ft
->encoding
.encoding
) {
793 ft
->encoding
.bits_per_sample
= 65;
795 while ((e
= enc_arg(sox_encoding_t
)))
796 while ((s
= enc_arg(unsigned)))
797 if (!(sox_encodings_info
[e
].flags
& (sox_encodings_lossy1
| sox_encodings_lossy2
)) &&
798 sox_precision(e
, s
) >= ft
->signal
.precision
&& s
< ft
->encoding
.bits_per_sample
) {
799 ft
->encoding
.encoding
= e
;
800 ft
->encoding
.bits_per_sample
= s
;
804 /* Find the smallest lossy encoding with precision >= signal precision,
805 * or, if none such, the highest precision encoding */
806 if (!ft
->encoding
.encoding
) {
808 sox_encoding_t max_p_e
= 0;
809 unsigned max_p_s
= 0;
811 while ((e
= enc_arg(sox_encoding_t
)))
813 s
= enc_arg(unsigned);
814 if (sox_precision(e
, s
) >= ft
->signal
.precision
) {
815 if (s
< ft
->encoding
.bits_per_sample
) {
816 ft
->encoding
.encoding
= e
;
817 ft
->encoding
.bits_per_sample
= s
;
820 else if (sox_precision(e
, s
) > max_p
) {
821 max_p
= sox_precision(e
, s
);
826 if (!ft
->encoding
.encoding
) {
827 ft
->encoding
.encoding
= max_p_e
;
828 ft
->encoding
.bits_per_sample
= max_p_s
;
831 ft
->signal
.precision
= sox_precision(ft
->encoding
.encoding
, ft
->encoding
.bits_per_sample
);
835 sox_format_handler_t
const * sox_write_handler(
837 char const * filetype
,
838 char const * * filetype1
)
840 sox_format_handler_t
const * handler
;
842 if (!(handler
= sox_find_format(filetype
, sox_false
))) {
844 lsx_fail("no handler for given file type `%s'", filetype
);
849 if (!(filetype
= lsx_find_file_extension(path
))) {
851 lsx_fail("can't determine type of `%s'", path
);
854 if (!(handler
= sox_find_format(filetype
, sox_true
))) {
856 lsx_fail("no handler for file extension `%s'", filetype
);
861 if (!handler
->startwrite
&& !handler
->write
) {
863 lsx_fail("file type `%s' isn't writable", filetype
);
867 *filetype1
= filetype
;
871 static sox_format_t
* open_write(
873 void * buffer UNUSED
,
874 size_t buffer_size UNUSED
,
875 char * * buffer_ptr UNUSED
,
876 size_t * buffer_size_ptr UNUSED
,
877 sox_signalinfo_t
const * signal
,
878 sox_encodinginfo_t
const * encoding
,
879 char const * filetype
,
880 sox_oob_t
const * oob
,
881 sox_bool (*overwrite_permitted
)(const char *filename
))
883 sox_format_t
* ft
= lsx_calloc(sizeof(*ft
), 1);
884 sox_format_handler_t
const * handler
;
886 if (!path
|| !signal
) {
887 lsx_fail("must specify file name and signal parameters to write file");
891 if (!(handler
= sox_write_handler(path
, filetype
, &filetype
)))
894 ft
->handler
= *handler
;
896 if (!(ft
->handler
.flags
& SOX_FILE_NOSTDIO
)) {
897 if (!strcmp(path
, "-")) { /* Use stdout if the filename is "-" */
898 if (sox_globals
.stdout_in_use_by
) {
899 lsx_fail("`-' (stdout) already in use by `%s'", sox_globals
.stdout_in_use_by
);
902 sox_globals
.stdout_in_use_by
= "audio output";
903 SET_BINARY_MODE(stdout
);
908 if (!stat(path
, &st
) && (st
.st_mode
& S_IFMT
) == S_IFREG
&&
909 (overwrite_permitted
&& !overwrite_permitted(path
))) {
910 lsx_fail("permission to overwrite `%s' denied", path
);
915 buffer
? fmemopen(buffer
, buffer_size
, "w+b") :
916 buffer_ptr
? open_memstream(buffer_ptr
, buffer_size_ptr
) :
919 if (ft
->fp
== NULL
) {
920 lsx_fail("can't open output file `%s': %s", path
, strerror(errno
));
925 /* stdout tends to be line-buffered. Override this */
926 /* to be Full Buffering. */
927 if (setvbuf (ft
->fp
, NULL
, _IOFBF
, sizeof(char) * sox_globals
.bufsiz
)) {
928 lsx_fail("Can't set write buffer");
931 ft
->seekable
= is_seekable(ft
);
934 ft
->filetype
= lsx_strdup(filetype
);
935 ft
->filename
= lsx_strdup(path
);
937 ft
->signal
= *signal
;
940 ft
->encoding
= *encoding
;
941 else sox_init_encodinginfo(&ft
->encoding
);
942 set_endiannesses(ft
);
947 ft
->oob
.comments
= sox_copy_comments(oob
->comments
);
950 set_output_format(ft
);
952 /* FIXME: doesn't cover the situation where
953 * codec changes audio length due to block alignment (e.g. 8svx, gsm): */
954 if (signal
->rate
&& signal
->channels
)
955 ft
->signal
.length
= ft
->signal
.length
* ft
->signal
.rate
/ signal
->rate
*
956 ft
->signal
.channels
/ signal
->channels
+ .5;
958 if ((ft
->handler
.flags
& SOX_FILE_REWIND
) && strcmp(ft
->filetype
, "sox") && !ft
->signal
.length
&& !ft
->seekable
)
959 lsx_warn("can't seek in output file `%s'; length in file header will be unspecified", ft
->filename
);
961 ft
->priv
= lsx_calloc(1, ft
->handler
.priv_size
);
962 /* Read and write starters can change their formats. */
963 if (ft
->handler
.startwrite
&& (ft
->handler
.startwrite
)(ft
) != SOX_SUCCESS
){
964 lsx_fail("can't open output file `%s': %s", ft
->filename
, ft
->sox_errstr
);
968 if (sox_checkformat(ft
) != SOX_SUCCESS
) {
969 lsx_fail("bad format for output file `%s': %s", ft
->filename
, ft
->sox_errstr
);
973 if ((ft
->handler
.flags
& SOX_FILE_DEVICE
) && signal
) {
974 if (signal
->rate
&& signal
->rate
!= ft
->signal
.rate
)
975 lsx_report("can't set sample rate %g; using %g", signal
->rate
, ft
->signal
.rate
);
976 if (signal
->channels
&& signal
->channels
!= ft
->signal
.channels
)
977 lsx_report("can't set %u channels; using %u", signal
->channels
, ft
->signal
.channels
);
982 if (ft
->fp
&& ft
->fp
!= stdout
)
983 xfclose(ft
->fp
, ft
->io_type
);
991 sox_format_t
* sox_open_write(
993 sox_signalinfo_t
const * signal
,
994 sox_encodinginfo_t
const * encoding
,
995 char const * filetype
,
996 sox_oob_t
const * oob
,
997 sox_bool (*overwrite_permitted
)(const char *filename
))
999 return open_write(path
, NULL
, (size_t)0, NULL
, NULL
, signal
, encoding
, filetype
, oob
, overwrite_permitted
);
1002 sox_format_t
* sox_open_mem_write(
1005 sox_signalinfo_t
const * signal
,
1006 sox_encodinginfo_t
const * encoding
,
1007 char const * filetype
,
1008 sox_oob_t
const * oob
)
1010 return open_write("", buffer
, buffer_size
, NULL
, NULL
, signal
, encoding
, filetype
, oob
, NULL
);
1013 sox_format_t
* sox_open_memstream_write(
1014 char * * buffer_ptr
,
1015 size_t * buffer_size_ptr
,
1016 sox_signalinfo_t
const * signal
,
1017 sox_encodinginfo_t
const * encoding
,
1018 char const * filetype
,
1019 sox_oob_t
const * oob
)
1021 return open_write("", NULL
, (size_t)0, buffer_ptr
, buffer_size_ptr
, signal
, encoding
, filetype
, oob
, NULL
);
1024 size_t sox_read(sox_format_t
* ft
, sox_sample_t
* buf
, size_t len
)
1027 if (ft
->signal
.length
!= SOX_UNSPEC
)
1028 len
= min(len
, ft
->signal
.length
- ft
->olength
);
1029 actual
= ft
->handler
.read
? (*ft
->handler
.read
)(ft
, buf
, len
) : 0;
1030 actual
= actual
> len
? 0 : actual
;
1031 ft
->olength
+= actual
;
1035 size_t sox_write(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t len
)
1037 size_t actual
= ft
->handler
.write
? (*ft
->handler
.write
)(ft
, buf
, len
) : 0;
1038 ft
->olength
+= actual
;
1042 int sox_close(sox_format_t
* ft
)
1044 int result
= SOX_SUCCESS
;
1046 if (ft
->mode
== 'r')
1047 result
= ft
->handler
.stopread
? (*ft
->handler
.stopread
)(ft
) : SOX_SUCCESS
;
1049 if (ft
->handler
.flags
& SOX_FILE_REWIND
) {
1050 if (ft
->olength
!= ft
->signal
.length
&& ft
->seekable
) {
1051 result
= lsx_seeki(ft
, (off_t
)0, 0);
1052 if (result
== SOX_SUCCESS
)
1053 result
= ft
->handler
.stopwrite
? (*ft
->handler
.stopwrite
)(ft
)
1054 : ft
->handler
.startwrite
?(*ft
->handler
.startwrite
)(ft
) : SOX_SUCCESS
;
1057 else result
= ft
->handler
.stopwrite
? (*ft
->handler
.stopwrite
)(ft
) : SOX_SUCCESS
;
1060 if (ft
->fp
== stdin
) {
1061 sox_globals
.stdin_in_use_by
= NULL
;
1062 } else if (ft
->fp
== stdout
) {
1064 sox_globals
.stdout_in_use_by
= NULL
;
1065 } else if (ft
->fp
) {
1066 xfclose(ft
->fp
, ft
->io_type
);
1072 sox_delete_comments(&ft
->oob
.comments
);
1078 int sox_seek(sox_format_t
* ft
, sox_uint64_t offset
, int whence
)
1080 /* FIXME: Implement SOX_SEEK_CUR and SOX_SEEK_END. */
1081 if (whence
!= SOX_SEEK_SET
)
1082 return SOX_EOF
; /* FIXME: return SOX_EINVAL */
1084 /* If file is a seekable file and this handler supports seeking,
1085 * then invoke handler's function.
1087 if (ft
->seekable
&& ft
->handler
.seek
)
1088 return (*ft
->handler
.seek
)(ft
, offset
);
1089 return SOX_EOF
; /* FIXME: return SOX_EBADF */
1092 static int strcaseends(char const * str
, char const * end
)
1094 size_t str_len
= strlen(str
), end_len
= strlen(end
);
1095 return str_len
>= end_len
&& !strcasecmp(str
+ str_len
- end_len
, end
);
1098 typedef enum {None
, M3u
, Pls
} playlist_t
;
1100 static playlist_t
playlist_type(char const * filename
)
1103 playlist_t result
= None
;
1105 if (*filename
== '|')
1107 if (strcaseends(filename
, ".m3u"))
1109 if (strcaseends(filename
, ".pls"))
1111 x
= lsx_strdup(filename
);
1112 p
= strrchr(x
, '?');
1115 result
= playlist_type(x
);
1121 sox_bool
sox_is_playlist(char const * filename
)
1123 return playlist_type(filename
) != None
;
1126 int sox_parse_playlist(sox_playlist_callback_t callback
, void * p
, char const * const listname
)
1128 sox_bool
const is_pls
= playlist_type(listname
) == Pls
;
1129 int const comment_char
= "#;"[is_pls
];
1130 size_t text_length
= 100;
1131 char * text
= lsx_malloc(text_length
+ 1);
1132 char * dirname
= lsx_strdup(listname
);
1133 char * slash_pos
= LAST_SLASH(dirname
);
1134 lsx_io_type io_type
;
1135 FILE * file
= xfopen(listname
, "r", &io_type
);
1137 int c
, result
= SOX_SUCCESS
;
1145 lsx_fail("Can't open playlist file `%s': %s", listname
, strerror(errno
));
1151 size_t begin
= 0, end
= 0;
1153 while (isspace(c
= getc(file
)));
1156 while (c
!= EOF
&& !strchr("\r\n", c
) && c
!= comment_char
) {
1157 if (i
== text_length
)
1158 text
= lsx_realloc(text
, (text_length
<<= 1) + 1);
1160 if (!strchr(" \t\f", c
))
1166 if (c
== comment_char
) {
1168 while (c
!= EOF
&& !strchr("\r\n", c
));
1175 if (!strncasecmp(text
, "file", (size_t) 4) && sscanf(text
+ 4, "%*u=%c", &dummy
) == 1)
1176 begin
= strchr(text
+ 5, '=') - text
+ 1;
1180 char const * id
= text
+ begin
;
1182 if (!dirname
[0] || is_url(id
) || IS_ABSOLUTE(id
))
1183 filename
= lsx_strdup(id
);
1185 filename
= lsx_malloc(strlen(dirname
) + strlen(id
) + 2);
1186 sprintf(filename
, "%s/%s", dirname
, id
);
1188 if (sox_is_playlist(filename
))
1189 sox_parse_playlist(callback
, p
, filename
);
1190 else if (callback(p
, filename
))
1197 lsx_fail("error reading playlist file `%s': %s", listname
, strerror(errno
));
1200 if (xfclose(file
, io_type
) && io_type
== lsx_io_url
) {
1201 lsx_fail("error reading playlist file URL `%s'", listname
);
1210 /*----------------------------- Formats library ------------------------------*/
1213 #define FORMAT(f) f,
1214 #include "formats.h"
1219 static sox_bool plugins_initted
= sox_false
;
1221 #ifdef HAVE_LIBLTDL /* Plugin format handlers */
1222 #define MAX_DYNAMIC_FORMATS 42
1223 #define MAX_FORMATS (NSTATIC_FORMATS + MAX_DYNAMIC_FORMATS)
1224 #define MAX_FORMATS_1 (MAX_FORMATS + 1)
1225 #define MAX_NAME_LEN (size_t)1024 /* FIXME: Use vasprintf */
1227 #define MAX_FORMATS_1
1230 #define FORMAT(f) extern sox_format_handler_t const * lsx_##f##_format_fn(void);
1231 #include "formats.h"
1234 static sox_format_tab_t s_sox_format_fns
[MAX_FORMATS_1
] = {
1235 #define FORMAT(f) {NULL, lsx_##f##_format_fn},
1236 #include "formats.h"
1241 const sox_format_tab_t
*
1242 sox_get_format_fns(void)
1244 return s_sox_format_fns
;
1247 static unsigned nformats
= NSTATIC_FORMATS
;
1249 #ifdef HAVE_LIBLTDL /* Plugin format handlers */
1251 static int init_format(const char *file
, lt_ptr data
)
1253 lt_dlhandle lth
= lt_dlopenext(file
);
1254 const char *end
= file
+ strlen(file
);
1255 const char prefix
[] = "sox_fmt_";
1256 char fnname
[MAX_NAME_LEN
];
1257 char *start
= strstr(file
, prefix
);
1260 if (start
&& (start
+= sizeof(prefix
) - 1) < end
) {
1261 int ret
= snprintf(fnname
, MAX_NAME_LEN
,
1262 "lsx_%.*s_format_fn", (int)(end
- start
), start
);
1263 if (ret
> 0 && ret
< (int)MAX_NAME_LEN
) {
1264 union {sox_format_fn_t fn
; lt_ptr ptr
;} ltptr
;
1265 ltptr
.ptr
= lt_dlsym(lth
, fnname
);
1266 lsx_debug("opening format plugin `%s': library %p, entry point %p\n",
1267 fnname
, (void *)lth
, ltptr
.ptr
);
1268 if (ltptr
.fn
&& (ltptr
.fn()->sox_lib_version_code
& ~255) ==
1269 (SOX_LIB_VERSION_CODE
& ~255)) { /* compatible version check */
1270 if (nformats
== MAX_FORMATS
) {
1271 lsx_warn("too many plugin formats");
1274 s_sox_format_fns
[nformats
++].fn
= ltptr
.fn
;
1282 int sox_format_init(void) /* Find & load format handlers. */
1284 if (plugins_initted
)
1287 plugins_initted
= sox_true
;
1290 int error
= lt_dlinit();
1292 lsx_fail("lt_dlinit failed with %d error(s): %s", error
, lt_dlerror());
1295 lt_dlforeachfile(PKGLIBDIR
, init_format
, NULL
);
1301 void sox_format_quit(void) /* Cleanup things. */
1305 if (plugins_initted
&& (ret
= lt_dlexit()) != 0)
1306 lsx_fail("lt_dlexit failed with %d error(s): %s", ret
, lt_dlerror());
1307 plugins_initted
= sox_false
;
1308 nformats
= NSTATIC_FORMATS
;
1312 /* Find a named format in the formats library.
1314 * (c) 2005-9 Chris Bagwell and SoX contributors.
1315 * Copyright 1991 Lance Norskog And Sundry Contributors.
1317 * This source code is freely redistributable and may be used for any
1318 * purpose. This copyright notice must be maintained.
1320 * Lance Norskog, Sundry Contributors, Chris Bagwell and SoX contributors
1321 * are not responsible for the consequences of using this software.
1323 sox_format_handler_t
const * sox_find_format(char const * name0
, sox_bool no_dev
)
1328 char * name
= lsx_strdup(name0
);
1329 char * pos
= strchr(name
, ';');
1330 if (pos
) /* Use only the 1st clause of a mime string */
1332 for (f
= 0; f
< nformats
; ++f
) {
1333 sox_format_handler_t
const * handler
= s_sox_format_fns
[f
].fn();
1335 if (!(no_dev
&& (handler
->flags
& SOX_FILE_DEVICE
)))
1336 for (n
= 0; handler
->names
[n
]; ++n
)
1337 if (!strcasecmp(handler
->names
[n
], name
)) {
1339 return handler
; /* Found it. */
1344 if (sox_format_init() == SOX_SUCCESS
) /* Try again with plugins */
1345 return sox_find_format(name0
, no_dev
);