formats: clarify setting of reverse_bytes
[sox.git] / src / mp3.c
blob33a371ed6a7968e8b7c56f428c74b7ea8be5a434
1 /* MP3 support for SoX
3 * Uses libmad for MP3 decoding
4 * libmp3lame for MP3 encoding
5 * and libtwolame for MP2 encoding
7 * Written by Fabrizio Gennari <fabrizio.ge@tiscali.it>
9 * The decoding part is based on the decoder-tutorial program madlld
10 * written by Bertrand Petit <madlld@phoe.fmug.org>,
13 #include "sox_i.h"
14 #include <string.h>
16 #if defined(HAVE_LAME_LAME_H) || defined(HAVE_LAME_H) || defined(DL_LAME)
17 #define HAVE_LAME 1
18 #endif
20 #if defined(HAVE_TWOLAME_H) || defined(DL_TWOLAME)
21 #define HAVE_TWOLAME 1
22 #endif
24 #if defined(HAVE_MAD_H) || defined(HAVE_LAME) || defined(HAVE_TWOLAME)
26 #ifdef HAVE_MAD_H
27 #include <mad.h>
28 #endif
30 #if defined(HAVE_LAME_LAME_H)
31 #include <lame/lame.h>
32 #elif defined(HAVE_LAME_H)
33 #include <lame.h>
34 #elif defined(DL_LAME)
35 typedef struct lame_global_struct lame_global_flags;
36 typedef enum {
37 vbr_off=0,
38 vbr_default=4
39 } vbr_mode;
40 #endif
42 #if defined(HAVE_ID3TAG) && (defined(HAVE_IO_H) || defined(HAVE_UNISTD_H))
43 #define USING_ID3TAG 1
44 #endif
46 #ifdef USING_ID3TAG
47 #include <id3tag.h>
48 #if defined(HAVE_UNISTD_H)
49 #include <unistd.h>
50 #elif defined(HAVE_IO_H)
51 #include <io.h>
52 #endif
53 #else
54 #define ID3_TAG_FLAG_FOOTERPRESENT 0x10
55 #endif
57 #ifdef HAVE_TWOLAME_H
58 #include <twolame.h>
59 #endif
61 /* Under Windows, importing data from DLLs is a dicey proposition. This is true
62 * when using dlopen, but also true if linking directly against the DLL if the
63 * header does not mark the data as __declspec(dllexport), which mad.h does not.
64 * Sidestep the issue by defining our own mad_timer_zero. This is needed because
65 * mad_timer_zero is used in some of the mad.h macros.
67 #ifdef HAVE_MAD_H
68 #define mad_timer_zero mad_timer_zero_stub
69 static mad_timer_t const mad_timer_zero_stub = {0, 0};
70 #endif
72 #define MAXFRAMESIZE 2880
73 #define ID3PADDING 128
75 /* LAME takes float values as input. */
76 #define MP3_LAME_PRECISION 24
78 /* MAD returns values with MAD_F_FRACBITS (28) bits of precision, though it's
79 not certain that all of them are meaningful. Default to 16 bits to
80 align with most users expectation of output file should be 16 bits. */
81 #define MP3_MAD_PRECISION 16
83 static const char* const mad_library_names[] =
85 #ifdef DL_MAD
86 "libmad",
87 "libmad-0",
88 "cygmad-0",
89 #endif
90 NULL
93 #ifdef DL_MAD
94 #define MAD_FUNC LSX_DLENTRY_DYNAMIC
95 #else
96 #define MAD_FUNC LSX_DLENTRY_STATIC
97 #endif
99 #define MAD_FUNC_ENTRIES(f,x) \
100 MAD_FUNC(f,x, void, mad_stream_buffer, (struct mad_stream *, unsigned char const *, unsigned long)) \
101 MAD_FUNC(f,x, void, mad_stream_skip, (struct mad_stream *, unsigned long)) \
102 MAD_FUNC(f,x, int, mad_stream_sync, (struct mad_stream *)) \
103 MAD_FUNC(f,x, void, mad_stream_init, (struct mad_stream *)) \
104 MAD_FUNC(f,x, void, mad_frame_init, (struct mad_frame *)) \
105 MAD_FUNC(f,x, void, mad_synth_init, (struct mad_synth *)) \
106 MAD_FUNC(f,x, int, mad_frame_decode, (struct mad_frame *, struct mad_stream *)) \
107 MAD_FUNC(f,x, void, mad_timer_add, (mad_timer_t *, mad_timer_t)) \
108 MAD_FUNC(f,x, void, mad_synth_frame, (struct mad_synth *, struct mad_frame const *)) \
109 MAD_FUNC(f,x, char const *, mad_stream_errorstr, (struct mad_stream const *)) \
110 MAD_FUNC(f,x, void, mad_frame_finish, (struct mad_frame *)) \
111 MAD_FUNC(f,x, void, mad_stream_finish, (struct mad_stream *)) \
112 MAD_FUNC(f,x, unsigned long, mad_bit_read, (struct mad_bitptr *, unsigned int)) \
113 MAD_FUNC(f,x, int, mad_header_decode, (struct mad_header *, struct mad_stream *)) \
114 MAD_FUNC(f,x, void, mad_header_init, (struct mad_header *)) \
115 MAD_FUNC(f,x, signed long, mad_timer_count, (mad_timer_t, enum mad_units)) \
116 MAD_FUNC(f,x, void, mad_timer_multiply, (mad_timer_t *, signed long))
118 static const char* const lame_library_names[] =
120 #ifdef DL_LAME
121 "libmp3lame",
122 "libmp3lame-0",
123 "lame-enc",
124 "cygmp3lame-0",
125 #endif
126 NULL
129 #ifdef DL_LAME
130 #define LAME_FUNC LSX_DLENTRY_DYNAMIC
131 #else /* DL_LAME */
132 #define LAME_FUNC LSX_DLENTRY_STATIC
133 #endif /* DL_LAME */
135 #define LAME_FUNC_ENTRIES(f,x) \
136 LAME_FUNC(f,x, lame_global_flags*, lame_init, (void)) \
137 LAME_FUNC(f,x, int, lame_set_errorf, (lame_global_flags *, void (*)(const char *, va_list))) \
138 LAME_FUNC(f,x, int, lame_set_debugf, (lame_global_flags *, void (*)(const char *, va_list))) \
139 LAME_FUNC(f,x, int, lame_set_msgf, (lame_global_flags *, void (*)(const char *, va_list))) \
140 LAME_FUNC(f,x, int, lame_set_num_samples, (lame_global_flags *, unsigned long)) \
141 LAME_FUNC(f,x, int, lame_get_num_channels, (const lame_global_flags *)) \
142 LAME_FUNC(f,x, int, lame_set_num_channels, (lame_global_flags *, int)) \
143 LAME_FUNC(f,x, int, lame_set_in_samplerate, (lame_global_flags *, int)) \
144 LAME_FUNC(f,x, int, lame_set_out_samplerate, (lame_global_flags *, int)) \
145 LAME_FUNC(f,x, int, lame_set_bWriteVbrTag, (lame_global_flags *, int)) \
146 LAME_FUNC(f,x, int, lame_set_brate, (lame_global_flags *, int)) \
147 LAME_FUNC(f,x, int, lame_set_quality, (lame_global_flags *, int)) \
148 LAME_FUNC(f,x, vbr_mode, lame_get_VBR, (const lame_global_flags *)) \
149 LAME_FUNC(f,x, int, lame_set_VBR, (lame_global_flags *, vbr_mode)) \
150 LAME_FUNC(f,x, int, lame_set_VBR_q, (lame_global_flags *, int)) \
151 LAME_FUNC(f,x, int, lame_init_params, (lame_global_flags *)) \
152 LAME_FUNC(f,x, int, lame_encode_buffer_float, (lame_global_flags *, const float[], const float[], const int, unsigned char *, const int)) \
153 LAME_FUNC(f,x, int, lame_encode_flush, (lame_global_flags *, unsigned char *, int)) \
154 LAME_FUNC(f,x, int, lame_close, (lame_global_flags *)) \
155 LAME_FUNC(f,x, size_t, lame_get_lametag_frame, (const lame_global_flags *, unsigned char*, size_t)) \
156 LAME_FUNC(f,x, void, id3tag_init, (lame_global_flags *)) \
157 LAME_FUNC(f,x, void, id3tag_set_title, (lame_global_flags *, const char* title)) \
158 LAME_FUNC(f,x, void, id3tag_set_artist, (lame_global_flags *, const char* artist)) \
159 LAME_FUNC(f,x, void, id3tag_set_album, (lame_global_flags *, const char* album)) \
160 LAME_FUNC(f,x, void, id3tag_set_year, (lame_global_flags *, const char* year)) \
161 LAME_FUNC(f,x, void, id3tag_set_comment, (lame_global_flags *, const char* comment)) \
162 LAME_FUNC(f,x, int, id3tag_set_track, (lame_global_flags *, const char* track)) \
163 LAME_FUNC(f,x, int, id3tag_set_genre, (lame_global_flags *, const char* genre)) \
164 LAME_FUNC(f,x, size_t, id3tag_set_pad, (lame_global_flags *, size_t)) \
165 LAME_FUNC(f,x, size_t, lame_get_id3v2_tag, (lame_global_flags *, unsigned char*, size_t)) \
166 LAME_FUNC(f,x, int, id3tag_set_fieldvalue, (lame_global_flags *, const char *))
168 #ifdef HAVE_TWOLAME
169 static const char* const twolame_library_names[] =
171 #ifdef DL_TWOLAME
172 "libtwolame",
173 "libtwolame-0",
174 #endif
175 NULL
177 #endif
179 #ifdef DL_TWOLAME
180 #define TWOLAME_FUNC LSX_DLENTRY_DYNAMIC
181 #else
182 #define TWOLAME_FUNC LSX_DLENTRY_STATIC
183 #endif
185 #define TWOLAME_FUNC_ENTRIES(f,x) \
186 TWOLAME_FUNC(f,x, twolame_options*, twolame_init, (void)) \
187 TWOLAME_FUNC(f,x, int, twolame_get_num_channels, (twolame_options*)) \
188 TWOLAME_FUNC(f,x, int, twolame_set_num_channels, (twolame_options*, int)) \
189 TWOLAME_FUNC(f,x, int, twolame_set_in_samplerate, (twolame_options *, int)) \
190 TWOLAME_FUNC(f,x, int, twolame_set_out_samplerate, (twolame_options *, int)) \
191 TWOLAME_FUNC(f,x, int, twolame_set_brate, (twolame_options *, int)) \
192 TWOLAME_FUNC(f,x, int, twolame_init_params, (twolame_options *)) \
193 TWOLAME_FUNC(f,x, int, twolame_encode_buffer_float32_interleaved, (twolame_options *, const float [], int, unsigned char *, int)) \
194 TWOLAME_FUNC(f,x, int, twolame_encode_flush, (twolame_options *, unsigned char *, int)) \
195 TWOLAME_FUNC(f,x, void, twolame_close, (twolame_options **))
197 /* Private data */
198 typedef struct mp3_priv_t {
199 unsigned char *mp3_buffer;
200 size_t mp3_buffer_size;
202 #ifdef HAVE_MAD_H
203 struct mad_stream Stream;
204 struct mad_frame Frame;
205 struct mad_synth Synth;
206 mad_timer_t Timer;
207 ptrdiff_t cursamp;
208 size_t FrameCount;
209 LSX_DLENTRIES_TO_PTRS(MAD_FUNC_ENTRIES, mad_dl);
210 #endif /*HAVE_MAD_H*/
212 #if defined(HAVE_LAME) || defined(HAVE_TWOLAME)
213 float *pcm_buffer;
214 size_t pcm_buffer_size;
215 char mp2;
216 #endif
218 #ifdef HAVE_LAME
219 lame_global_flags *gfp;
220 uint64_t num_samples;
221 int vbr_tag;
222 LSX_DLENTRIES_TO_PTRS(LAME_FUNC_ENTRIES, lame_dl);
223 #endif
225 #ifdef HAVE_TWOLAME
226 twolame_options *opt;
227 LSX_DLENTRIES_TO_PTRS(TWOLAME_FUNC_ENTRIES, twolame_dl);
228 #endif
229 } priv_t;
231 #ifdef HAVE_MAD_H
233 /* This function merges the functions tagtype() and id3_tag_query()
234 from MAD's libid3tag, so we don't have to link to it
235 Returns 0 if the frame is not an ID3 tag, tag length if it is */
237 static int tagtype(const unsigned char *data, size_t length)
239 if (length >= 3 && data[0] == 'T' && data[1] == 'A' && data[2] == 'G')
241 return 128; /* ID3V1 */
244 if (length >= 10 &&
245 (data[0] == 'I' && data[1] == 'D' && data[2] == '3') &&
246 data[3] < 0xff && data[4] < 0xff &&
247 data[6] < 0x80 && data[7] < 0x80 && data[8] < 0x80 && data[9] < 0x80)
248 { /* ID3V2 */
249 unsigned char flags;
250 unsigned int size;
251 flags = data[5];
252 size = 10 + (data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9];
253 if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
254 size += 10;
255 for (; size < length && !data[size]; ++size); /* Consume padding */
256 return size;
259 return 0;
262 #endif /*HAVE_MAD_H*/
264 #include "mp3-util.h"
266 #ifdef HAVE_MAD_H
269 * (Re)fill the stream buffer that is to be decoded. If any data
270 * still exists in the buffer then they are first shifted to be
271 * front of the stream buffer.
273 static int sox_mp3_input(sox_format_t * ft)
275 priv_t *p = (priv_t *) ft->priv;
276 size_t bytes_read;
277 size_t remaining;
279 remaining = p->Stream.bufend - p->Stream.next_frame;
281 /* libmad does not consume all the buffer it's given. Some
282 * data, part of a truncated frame, is left unused at the
283 * end of the buffer. That data must be put back at the
284 * beginning of the buffer and taken in account for
285 * refilling the buffer. This means that the input buffer
286 * must be large enough to hold a complete frame at the
287 * highest observable bit-rate (currently 448 kb/s).
288 * TODO: Is 2016 bytes the size of the largest frame?
289 * (448000*(1152/32000))/8
291 memmove(p->mp3_buffer, p->Stream.next_frame, remaining);
293 bytes_read = lsx_readbuf(ft, p->mp3_buffer+remaining,
294 p->mp3_buffer_size-remaining);
295 if (bytes_read == 0)
297 return SOX_EOF;
300 p->mad_stream_buffer(&p->Stream, p->mp3_buffer, bytes_read+remaining);
301 p->Stream.error = 0;
303 return SOX_SUCCESS;
306 /* Attempts to read an ID3 tag at the current location in stream and
307 * consume it all. Returns SOX_EOF if no tag is found. Its up to
308 * caller to recover.
309 * */
310 static int sox_mp3_inputtag(sox_format_t * ft)
312 priv_t *p = (priv_t *) ft->priv;
313 int rc = SOX_EOF;
314 size_t remaining;
315 size_t tagsize;
318 /* FIXME: This needs some more work if we are to ever
319 * look at the ID3 frame. This is because the Stream
320 * may not be able to hold the complete ID3 frame.
321 * We should consume the whole frame inside tagtype()
322 * instead of outside of tagframe(). That would support
323 * recovering when Stream contains less then 8-bytes (header)
324 * and also when ID3v2 is bigger then Stream buffer size.
325 * Need to pass in stream so that buffer can be
326 * consumed as well as letting additional data to be
327 * read in.
329 remaining = p->Stream.bufend - p->Stream.next_frame;
330 if ((tagsize = tagtype(p->Stream.this_frame, remaining)))
332 p->mad_stream_skip(&p->Stream, tagsize);
333 rc = SOX_SUCCESS;
336 /* We know that a valid frame hasn't been found yet
337 * so help libmad out and go back into frame seek mode.
338 * This is true whether an ID3 tag was found or not.
340 p->mad_stream_sync(&p->Stream);
342 return rc;
345 static sox_bool sox_mp3_vbrtag(sox_format_t *ft)
347 priv_t *p = ft->priv;
348 struct mad_bitptr *anc = &p->Stream.anc_ptr;
350 if (p->Frame.header.layer != MAD_LAYER_III)
351 return sox_false;
353 if (p->Stream.anc_bitlen < 32)
354 return sox_false;
356 if (!memcmp(anc->byte, "Xing", 4) ||
357 !memcmp(anc->byte, "Info", 4))
358 return sox_true;
360 return sox_false;
363 static int startread(sox_format_t * ft)
365 priv_t *p = (priv_t *) ft->priv;
366 size_t ReadSize;
367 sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
368 int open_library_result;
370 LSX_DLLIBRARY_OPEN(
372 mad_dl,
373 MAD_FUNC_ENTRIES,
374 "MAD decoder library",
375 mad_library_names,
376 open_library_result);
377 if (open_library_result)
378 return SOX_EOF;
380 p->mp3_buffer_size = sox_globals.bufsiz;
381 p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);
383 ft->signal.length = SOX_UNSPEC;
384 if (ft->seekable) {
385 #ifdef USING_ID3TAG
386 read_comments(ft);
387 lsx_rewind(ft);
388 if (!ft->signal.length)
389 #endif
390 if (!ignore_length)
391 ft->signal.length = mp3_duration(ft);
394 p->mad_stream_init(&p->Stream);
395 p->mad_frame_init(&p->Frame);
396 p->mad_synth_init(&p->Synth);
397 mad_timer_reset(&p->Timer);
399 ft->encoding.encoding = SOX_ENCODING_MP3;
401 /* Decode at least one valid frame to find out the input
402 * format. The decoded frame will be saved off so that it
403 * can be processed later.
405 ReadSize = lsx_readbuf(ft, p->mp3_buffer, p->mp3_buffer_size);
406 if (ReadSize != p->mp3_buffer_size && lsx_error(ft))
407 return SOX_EOF;
409 p->mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);
411 /* Find a valid frame before starting up. This makes sure
412 * that we have a valid MP3 and also skips past ID3v2 tags
413 * at the beginning of the audio file.
415 p->Stream.error = 0;
416 while (p->mad_frame_decode(&p->Frame,&p->Stream))
418 /* check whether input buffer needs a refill */
419 if (p->Stream.error == MAD_ERROR_BUFLEN)
421 if (sox_mp3_input(ft) == SOX_EOF)
422 return SOX_EOF;
424 continue;
427 /* Consume any ID3 tags */
428 sox_mp3_inputtag(ft);
430 /* FIXME: We should probably detect when we've read
431 * a bunch of non-ID3 data and still haven't found a
432 * frame. In that case we can abort early without
433 * scanning the whole file.
435 p->Stream.error = 0;
438 if (p->Stream.error)
440 lsx_fail_errno(ft,SOX_EOF,"No valid MP3 frame found");
441 return SOX_EOF;
444 switch(p->Frame.header.mode)
446 case MAD_MODE_SINGLE_CHANNEL:
447 case MAD_MODE_DUAL_CHANNEL:
448 case MAD_MODE_JOINT_STEREO:
449 case MAD_MODE_STEREO:
450 ft->signal.channels = MAD_NCHANNELS(&p->Frame.header);
451 break;
452 default:
453 lsx_fail_errno(ft, SOX_EFMT, "Cannot determine number of channels");
454 return SOX_EOF;
457 ft->signal.precision = MP3_MAD_PRECISION;
458 ft->signal.rate=p->Frame.header.samplerate;
459 if (ignore_length)
460 ft->signal.length = SOX_UNSPEC;
461 else {
462 ft->signal.length *= ft->signal.channels; /* Keep separate from line above! */
465 if (!sox_mp3_vbrtag(ft))
466 p->Stream.next_frame = p->Stream.this_frame;
468 p->mad_frame_init(&p->Frame);
469 sox_mp3_input(ft);
471 p->cursamp = 0;
473 return SOX_SUCCESS;
477 * Read up to len samples from p->Synth
478 * If needed, read some more MP3 data, decode them and synth them
479 * Place in buf[].
480 * Return number of samples read.
482 static size_t sox_mp3read(sox_format_t * ft, sox_sample_t *buf, size_t len)
484 priv_t *p = (priv_t *) ft->priv;
485 size_t donow,i,done=0;
486 mad_fixed_t sample;
487 size_t chan;
489 do {
490 size_t x = (p->Synth.pcm.length - p->cursamp)*ft->signal.channels;
491 donow=min(len, x);
492 i=0;
493 while(i<donow){
494 for(chan=0;chan<ft->signal.channels;chan++){
495 sample=p->Synth.pcm.samples[chan][p->cursamp];
496 if (sample < -MAD_F_ONE)
497 sample=-MAD_F_ONE;
498 else if (sample >= MAD_F_ONE)
499 sample=MAD_F_ONE-1;
500 *buf++=(sox_sample_t)(sample<<(32-1-MAD_F_FRACBITS));
501 i++;
503 p->cursamp++;
506 len-=donow;
507 done+=donow;
509 if (len==0) break;
511 /* check whether input buffer needs a refill */
512 if (p->Stream.error == MAD_ERROR_BUFLEN)
514 if (sox_mp3_input(ft) == SOX_EOF) {
515 lsx_debug("sox_mp3_input EOF");
516 break;
520 if (p->mad_frame_decode(&p->Frame,&p->Stream))
522 if(MAD_RECOVERABLE(p->Stream.error))
524 sox_mp3_inputtag(ft);
525 continue;
527 else
529 if (p->Stream.error == MAD_ERROR_BUFLEN)
530 continue;
531 else
533 lsx_report("unrecoverable frame level error (%s).",
534 p->mad_stream_errorstr(&p->Stream));
535 break;
539 p->FrameCount++;
540 p->mad_timer_add(&p->Timer,p->Frame.header.duration);
541 p->mad_synth_frame(&p->Synth,&p->Frame);
542 p->cursamp=0;
543 } while(1);
545 return done;
548 static int stopread(sox_format_t * ft)
550 priv_t *p=(priv_t*) ft->priv;
552 mad_synth_finish(&p->Synth);
553 p->mad_frame_finish(&p->Frame);
554 p->mad_stream_finish(&p->Stream);
556 free(p->mp3_buffer);
557 LSX_DLLIBRARY_CLOSE(p, mad_dl);
558 return SOX_SUCCESS;
561 static int sox_mp3seek(sox_format_t * ft, uint64_t offset)
563 priv_t * p = (priv_t *) ft->priv;
564 size_t initial_bitrate = p->Frame.header.bitrate;
565 size_t tagsize = 0, consumed = 0;
566 sox_bool vbr = sox_false; /* Variable Bit Rate */
567 sox_bool depadded = sox_false;
568 uint64_t to_skip_samples = 0;
570 /* Reset all */
571 lsx_rewind(ft);
572 mad_timer_reset(&p->Timer);
573 p->FrameCount = 0;
575 /* They where opened in startread */
576 mad_synth_finish(&p->Synth);
577 p->mad_frame_finish(&p->Frame);
578 p->mad_stream_finish(&p->Stream);
580 p->mad_stream_init(&p->Stream);
581 p->mad_frame_init(&p->Frame);
582 p->mad_synth_init(&p->Synth);
584 offset /= ft->signal.channels;
585 to_skip_samples = offset;
587 while(sox_true) { /* Read data from the MP3 file */
588 size_t padding = 0;
589 size_t read;
590 size_t leftover = p->Stream.bufend - p->Stream.next_frame;
592 memmove(p->mp3_buffer, p->Stream.this_frame, leftover);
593 read = lsx_readbuf(ft, p->mp3_buffer + leftover, p->mp3_buffer_size - leftover);
594 if (read == 0) {
595 lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover);
596 break;
598 for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding);
599 depadded = sox_true;
600 p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding);
602 while (sox_true) { /* Decode frame headers */
603 static unsigned short samples;
604 p->Stream.error = MAD_ERROR_NONE;
606 /* Not an audio frame */
607 if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) {
608 if (p->Stream.error == MAD_ERROR_BUFLEN)
609 break; /* Normal behaviour; get some more data from the file */
610 if (!MAD_RECOVERABLE(p->Stream.error)) {
611 lsx_warn("unrecoverable MAD error");
612 break;
614 if (p->Stream.error == MAD_ERROR_LOSTSYNC) {
615 unsigned available = (p->Stream.bufend - p->Stream.this_frame);
616 tagsize = tagtype(p->Stream.this_frame, (size_t) available);
617 if (tagsize) { /* It's some ID3 tags, so just skip */
618 if (tagsize >= available) {
619 lsx_seeki(ft, (off_t)(tagsize - available), SEEK_CUR);
620 depadded = sox_false;
622 p->mad_stream_skip(&p->Stream, min(tagsize, available));
624 else lsx_warn("MAD lost sync");
626 else lsx_warn("recoverable MAD error");
627 continue;
630 consumed += p->Stream.next_frame - p->Stream.this_frame;
631 vbr |= (p->Frame.header.bitrate != initial_bitrate);
633 samples = 32 * MAD_NSBSAMPLES(&p->Frame.header);
635 p->FrameCount++;
636 p->mad_timer_add(&p->Timer, p->Frame.header.duration);
638 if(to_skip_samples <= samples)
640 p->mad_frame_decode(&p->Frame,&p->Stream);
641 p->mad_synth_frame(&p->Synth, &p->Frame);
642 p->cursamp = to_skip_samples;
643 return SOX_SUCCESS;
645 else to_skip_samples -= samples;
647 /* If not VBR, we can extrapolate frame size */
648 if (p->FrameCount == 64 && !vbr) {
649 p->FrameCount = offset / samples;
650 to_skip_samples = offset % samples;
652 if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET))
653 return SOX_EOF;
655 /* Reset Stream for refilling buffer */
656 p->mad_stream_finish(&p->Stream);
657 p->mad_stream_init(&p->Stream);
658 break;
663 return SOX_EOF;
665 #else /* !HAVE_MAD_H */
666 static int startread(sox_format_t * ft)
668 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP3 decoding support");
669 return SOX_EOF;
671 #define sox_mp3read NULL
672 #define stopread NULL
673 #define sox_mp3seek NULL
674 #endif /*HAVE_MAD_H*/
676 #ifdef HAVE_LAME
678 /* Adapters for lame message callbacks: */
680 static void errorf(const char* fmt, va_list va)
682 sox_globals.subsystem=__FILE__;
683 if (sox_globals.output_message_handler)
684 (*sox_globals.output_message_handler)(1,sox_globals.subsystem,fmt,va);
685 return;
688 static void debugf(const char* fmt, va_list va)
690 sox_globals.subsystem=__FILE__;
691 if (sox_globals.output_message_handler)
692 (*sox_globals.output_message_handler)(4,sox_globals.subsystem,fmt,va);
693 return;
696 static void msgf(const char* fmt, va_list va)
698 sox_globals.subsystem=__FILE__;
699 if (sox_globals.output_message_handler)
700 (*sox_globals.output_message_handler)(3,sox_globals.subsystem,fmt,va);
701 return;
704 /* These functions are considered optional. If they aren't present in the
705 library, the stub versions defined here will be used instead. */
707 UNUSED static void id3tag_init_stub(lame_global_flags * gfp UNUSED)
708 { return; }
709 UNUSED static void id3tag_set_title_stub(lame_global_flags * gfp UNUSED, const char* title UNUSED)
710 { return; }
711 UNUSED static void id3tag_set_artist_stub(lame_global_flags * gfp UNUSED, const char* artist UNUSED)
712 { return; }
713 UNUSED static void id3tag_set_album_stub(lame_global_flags * gfp UNUSED, const char* album UNUSED)
714 { return; }
715 UNUSED static void id3tag_set_year_stub(lame_global_flags * gfp UNUSED, const char* year UNUSED)
716 { return; }
717 UNUSED static void id3tag_set_comment_stub(lame_global_flags * gfp UNUSED, const char* comment UNUSED)
718 { return; }
719 UNUSED static void id3tag_set_track_stub(lame_global_flags * gfp UNUSED, const char* track UNUSED)
720 { return; }
721 UNUSED static int id3tag_set_genre_stub(lame_global_flags * gfp UNUSED, const char* genre UNUSED)
722 { return 0; }
723 UNUSED static size_t id3tag_set_pad_stub(lame_global_flags * gfp UNUSED, size_t n UNUSED)
724 { return 0; }
725 UNUSED static size_t lame_get_id3v2_tag_stub(lame_global_flags * gfp UNUSED, unsigned char * buffer UNUSED, size_t size UNUSED)
726 { return 0; }
727 UNUSED static int id3tag_set_fieldvalue_stub(lame_global_flags * gfp UNUSED, const char *fieldvalue UNUSED)
728 { return 0; }
730 static int get_id3v2_tag_size(sox_format_t * ft)
732 size_t bytes_read;
733 int id3v2_size;
734 unsigned char id3v2_header[10];
736 if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0) {
737 lsx_warn("cannot update id3 tag - failed to seek to beginning");
738 return SOX_EOF;
741 /* read 10 bytes in case there's an ID3 version 2 header here */
742 bytes_read = lsx_readbuf(ft, id3v2_header, sizeof(id3v2_header));
743 if (bytes_read != sizeof(id3v2_header)) {
744 lsx_warn("cannot update id3 tag - failed to read id3 header");
745 return SOX_EOF; /* not readable, maybe opened Write-Only */
748 /* does the stream begin with the ID3 version 2 file identifier? */
749 if (!strncmp((char *) id3v2_header, "ID3", (size_t)3)) {
750 /* the tag size (minus the 10-byte header) is encoded into four
751 * bytes where the most significant bit is clear in each byte */
752 id3v2_size = (((id3v2_header[6] & 0x7f) << 21)
753 | ((id3v2_header[7] & 0x7f) << 14)
754 | ((id3v2_header[8] & 0x7f) << 7)
755 | (id3v2_header[9] & 0x7f))
756 + sizeof(id3v2_header);
757 } else {
758 /* no ID3 version 2 tag in this stream */
759 id3v2_size = 0;
761 return id3v2_size;
764 static void rewrite_id3v2_tag(sox_format_t * ft, size_t id3v2_size, uint64_t num_samples)
766 priv_t *p = (priv_t *)ft->priv;
767 size_t new_size;
768 unsigned char * buffer;
770 if (LSX_DLFUNC_IS_STUB(p, lame_get_id3v2_tag))
772 if (p->num_samples)
773 lsx_warn("cannot update track length info - tag update not supported with this version of LAME. Track length will be incorrect.");
774 else
775 lsx_report("cannot update track length info - tag update not supported with this version of LAME. Track length will be unspecified.");
776 return;
779 buffer = lsx_malloc(id3v2_size);
780 if (!buffer)
782 lsx_warn("cannot update track length info - failed to allocate buffer");
783 return;
786 if (num_samples > ULONG_MAX)
788 lsx_warn("cannot accurately update track length info - file is too long");
789 num_samples = 0;
791 p->lame_set_num_samples(p->gfp, (unsigned long)num_samples);
792 lsx_debug("updated MP3 TLEN to %lu samples", (unsigned long)num_samples);
794 new_size = p->lame_get_id3v2_tag(p->gfp, buffer, id3v2_size);
796 if (new_size != id3v2_size && new_size-ID3PADDING <= id3v2_size) {
797 p->id3tag_set_pad(p->gfp, ID3PADDING + id3v2_size - new_size);
798 new_size = p->lame_get_id3v2_tag(p->gfp, buffer, id3v2_size);
801 if (new_size != id3v2_size) {
802 if (LSX_DLFUNC_IS_STUB(p, id3tag_set_pad))
804 if (p->num_samples)
805 lsx_warn("cannot update track length info - tag size adjustment not supported with this version of LAME. Track length will be invalid.");
806 else
807 lsx_report("cannot update track length info - tag size adjustment not supported with this version of LAME. Track length will be unspecified.");
809 else
810 lsx_warn("cannot update track length info - failed to adjust tag size");
811 } else {
812 lsx_seeki(ft, (off_t)0, SEEK_SET);
813 /* Overwrite the Id3v2 tag (this time TLEN should be accurate) */
814 if (lsx_writebuf(ft, buffer, id3v2_size) != 1) {
815 lsx_debug("Rewrote Id3v2 tag (%" PRIuPTR " bytes)", id3v2_size);
819 free(buffer);
822 static void rewrite_tags(sox_format_t * ft, uint64_t num_samples)
824 priv_t *p = (priv_t *)ft->priv;
826 off_t file_size;
827 size_t id3v2_size;
829 if (lsx_seeki(ft, (off_t)0, SEEK_END)) {
830 lsx_warn("cannot update tags - seek to end failed");
831 return;
834 /* Get file size */
835 file_size = lsx_tell(ft);
837 if (file_size == 0) {
838 lsx_warn("cannot update tags - file size is 0");
839 return;
842 id3v2_size = get_id3v2_tag_size(ft);
843 if (id3v2_size > 0 && num_samples != p->num_samples) {
844 rewrite_id3v2_tag(ft, id3v2_size, num_samples);
847 if (p->vbr_tag) {
848 size_t lametag_size;
849 uint8_t buffer[MAXFRAMESIZE];
851 if (lsx_seeki(ft, (off_t)id3v2_size, SEEK_SET)) {
852 lsx_warn("cannot write VBR tag - seek to tag block failed");
853 return;
856 lametag_size = p->lame_get_lametag_frame(p->gfp, buffer, sizeof(buffer));
857 if (lametag_size > sizeof(buffer)) {
858 lsx_warn("cannot write VBR tag - VBR tag too large for buffer");
859 return;
862 if (lametag_size < 1) {
863 return;
866 if (lsx_writebuf(ft, buffer, lametag_size) != lametag_size) {
867 lsx_warn("cannot write VBR tag - VBR tag write failed");
868 } else {
869 lsx_debug("rewrote VBR tag (%" PRIuPTR " bytes)", lametag_size);
874 #endif /* HAVE_LAME */
876 #if defined(HAVE_LAME) || defined(HAVE_TWOLAME)
878 #define LAME_BUFFER_SIZE(num_samples) (((num_samples) + 3) / 4 * 5 + 7200)
880 static int startwrite(sox_format_t * ft)
882 priv_t *p = (priv_t *) ft->priv;
883 int openlibrary_result;
884 int fail = 0;
886 if (ft->encoding.encoding != SOX_ENCODING_MP3) {
887 if(ft->encoding.encoding != SOX_ENCODING_UNKNOWN)
888 lsx_report("Encoding forced to MP2/MP3");
889 ft->encoding.encoding = SOX_ENCODING_MP3;
892 if(strchr(ft->filetype, '2'))
893 p->mp2 = 1;
895 if (p->mp2) {
896 #ifdef HAVE_TWOLAME
897 LSX_DLLIBRARY_OPEN(
899 twolame_dl,
900 TWOLAME_FUNC_ENTRIES,
901 "Twolame encoder library",
902 twolame_library_names,
903 openlibrary_result);
904 #else
905 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP2 encoding support");
906 return SOX_EOF;
907 #endif
908 } else {
909 #ifdef HAVE_LAME
910 LSX_DLLIBRARY_OPEN(
912 lame_dl,
913 LAME_FUNC_ENTRIES,
914 "LAME encoder library",
915 lame_library_names,
916 openlibrary_result);
917 #else
918 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP3 encoding support");
919 return SOX_EOF;
920 #endif
922 if (openlibrary_result)
923 return SOX_EOF;
925 p->mp3_buffer_size = LAME_BUFFER_SIZE(sox_globals.bufsiz / max(ft->signal.channels, 1));
926 p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);
928 p->pcm_buffer_size = sox_globals.bufsiz * sizeof(float);
929 p->pcm_buffer = lsx_malloc(p->pcm_buffer_size);
931 if (p->mp2) {
932 #ifdef HAVE_TWOLAME
933 p->opt = p->twolame_init();
935 if (p->opt == NULL){
936 lsx_fail_errno(ft,SOX_EOF,"Initialization of Twolame library failed");
937 return(SOX_EOF);
939 #endif
940 } else {
941 #ifdef HAVE_LAME
942 p->gfp = p->lame_init();
944 if (p->gfp == NULL){
945 lsx_fail_errno(ft,SOX_EOF,"Initialization of LAME library failed");
946 return(SOX_EOF);
949 /* First set message callbacks so we don't miss any messages: */
950 p->lame_set_errorf(p->gfp,errorf);
951 p->lame_set_debugf(p->gfp,debugf);
952 p->lame_set_msgf (p->gfp,msgf);
954 p->num_samples = ft->signal.length == SOX_IGNORE_LENGTH ? 0 : ft->signal.length / max(ft->signal.channels, 1);
955 p->lame_set_num_samples(p->gfp, p->num_samples > ULONG_MAX ? 0 : (unsigned long)p->num_samples);
956 #endif
959 ft->signal.precision = MP3_LAME_PRECISION;
961 if (ft->signal.channels != SOX_ENCODING_UNKNOWN) {
962 if (p->mp2) {
963 #ifdef HAVE_TWOLAME
964 fail = (p->twolame_set_num_channels(p->opt,(int)ft->signal.channels) != 0);
965 #endif
966 } else {
967 #ifdef HAVE_LAME
968 fail = (p->lame_set_num_channels(p->gfp,(int)ft->signal.channels) < 0);
969 #endif
971 if (fail) {
972 lsx_fail_errno(ft,SOX_EOF,"Unsupported number of channels");
973 return(SOX_EOF);
976 else {
977 if (p->mp2) {
978 #ifdef HAVE_TWOLAME
979 ft->signal.channels = p->twolame_get_num_channels(p->opt); /* Twolame default */
980 #endif
981 } else {
982 #ifdef HAVE_LAME
983 ft->signal.channels = p->lame_get_num_channels(p->gfp); /* LAME default */
984 #endif
988 if (p->mp2) {
989 #ifdef HAVE_TWOLAME
990 p->twolame_set_in_samplerate(p->opt,(int)ft->signal.rate);
991 p->twolame_set_out_samplerate(p->opt,(int)ft->signal.rate);
992 #endif
993 } else {
994 #ifdef HAVE_LAME
995 p->lame_set_in_samplerate(p->gfp,(int)ft->signal.rate);
996 p->lame_set_out_samplerate(p->gfp,(int)ft->signal.rate);
997 #endif
1000 if (!p->mp2) {
1001 #ifdef HAVE_LAME
1002 if (!LSX_DLFUNC_IS_STUB(p, id3tag_init))
1003 write_comments(ft);
1004 #endif
1007 /* The primary parameter to the LAME encoder is the bit rate. If the
1008 * value of encoding.compression is a positive integer, it's taken as
1009 * the bitrate in kbps (that is if you specify 128, it use 128 kbps).
1011 * The second most important parameter is probably "quality" (really
1012 * performance), which allows balancing encoding speed vs. quality.
1013 * In LAME, 0 specifies highest quality but is very slow, while
1014 * 9 selects poor quality, but is fast. (5 is the default and 2 is
1015 * recommended as a good trade-off for high quality encodes.)
1017 * Because encoding.compression is a float, the fractional part is used
1018 * to select quality. 128.2 selects 128 kbps encoding with a quality
1019 * of 2. There is one problem with this approach. We need 128 to specify
1020 * 128 kbps encoding with default quality, so .0 means use default. Instead
1021 * of .0 you have to use .01 to specify the highest quality (128.01).
1023 * LAME uses bitrate to specify a constant bitrate, but higher quality
1024 * can be achieved using Variable Bit Rate (VBR). VBR quality (really
1025 * size) is selected using a number from 0 to 9. Use a value of 0 for high
1026 * quality, larger files, and 9 for smaller files of lower quality. 4 is
1027 * the default.
1029 * In order to squeeze the selection of VBR into the encoding.compression
1030 * float we use negative numbers to select VRR. -4.2 would select default
1031 * VBR encoding (size) with high quality (speed). One special case is 0,
1032 * which is a valid VBR encoding parameter but not a valid bitrate.
1033 * Compression value of 0 is always treated as a high quality vbr, as a
1034 * result both -0.2 and 0.2 are treated as highest quality VBR (size) and
1035 * high quality (speed).
1037 * Note: It would have been nice to simply use low values, 0-9, to trigger
1038 * VBR mode, but 8 kbps is a valid bit rate, so negative values were
1039 * used instead.
1042 lsx_debug("-C option is %f", ft->encoding.compression);
1044 if (ft->encoding.compression == HUGE_VAL) {
1045 /* Do nothing, use defaults: */
1046 lsx_report("using %s encoding defaults", p->mp2? "MP2" : "MP3");
1047 } else {
1048 double abs_compression = fabs(ft->encoding.compression);
1049 double floor_compression = floor(abs_compression);
1050 double fraction_compression = abs_compression - floor_compression;
1051 int bitrate_q = (int)floor_compression;
1052 int encoder_q =
1053 fraction_compression == 0.0
1054 ? -1
1055 : (int)(fraction_compression * 10.0 + 0.5);
1057 if (ft->encoding.compression < 0.5) {
1058 if (p->mp2) {
1059 lsx_fail_errno(ft,SOX_EOF,"Variable bitrate encoding not supported for MP2 audio");
1060 return(SOX_EOF);
1062 #ifdef HAVE_LAME
1063 if (p->lame_get_VBR(p->gfp) == vbr_off)
1064 p->lame_set_VBR(p->gfp, vbr_default);
1066 if (ft->seekable) {
1067 p->vbr_tag = 1;
1068 } else {
1069 lsx_warn("unable to write VBR tag because we can't seek");
1072 if (p->lame_set_VBR_q(p->gfp, bitrate_q) < 0)
1074 lsx_fail_errno(ft, SOX_EOF,
1075 "lame_set_VBR_q(%d) failed (should be between 0 and 9)",
1076 bitrate_q);
1077 return(SOX_EOF);
1079 lsx_report("lame_set_VBR_q(%d)", bitrate_q);
1080 #endif
1081 } else {
1082 if (p->mp2) {
1083 #ifdef HAVE_TWOLAME
1084 fail = (p->twolame_set_brate(p->opt, bitrate_q) != 0);
1085 #endif
1086 } else {
1087 #ifdef HAVE_LAME
1088 fail = (p->lame_set_brate(p->gfp, bitrate_q) < 0);
1089 #endif
1091 if (fail) {
1092 lsx_fail_errno(ft, SOX_EOF,
1093 "%slame_set_brate(%d) failed", p->mp2? "two" : "", bitrate_q);
1094 return(SOX_EOF);
1096 lsx_report("(two)lame_set_brate(%d)", bitrate_q);
1099 /* Set Quality */
1101 if (encoder_q < 0 || p->mp2) {
1102 /* use default quality value */
1103 lsx_report("using %s default quality", p->mp2? "MP2" : "MP3");
1104 } else {
1105 #ifdef HAVE_LAME
1106 if (p->lame_set_quality(p->gfp, encoder_q) < 0) {
1107 lsx_fail_errno(ft, SOX_EOF,
1108 "lame_set_quality(%d) failed", encoder_q);
1109 return(SOX_EOF);
1111 lsx_report("lame_set_quality(%d)", encoder_q);
1112 #endif
1116 if (!p->mp2) {
1117 #ifdef HAVE_LAME
1118 p->lame_set_bWriteVbrTag(p->gfp, p->vbr_tag);
1119 #endif
1122 if (p->mp2) {
1123 #ifdef HAVE_TWOLAME
1124 fail = (p->twolame_init_params(p->opt) != 0);
1125 #endif
1126 } else {
1127 #ifdef HAVE_LAME
1128 fail = (p->lame_init_params(p->gfp) < 0);
1129 #endif
1131 if (fail) {
1132 lsx_fail_errno(ft,SOX_EOF,"%s initialization failed", p->mp2? "Twolame" : "LAME");
1133 return(SOX_EOF);
1136 return(SOX_SUCCESS);
1139 #define MP3_SAMPLE_TO_FLOAT(d) ((float)(32768*SOX_SAMPLE_TO_FLOAT_32BIT(d,)))
1141 static size_t sox_mp3write(sox_format_t * ft, const sox_sample_t *buf, size_t samp)
1143 priv_t *p = (priv_t *)ft->priv;
1144 size_t new_buffer_size;
1145 float *buffer_l, *buffer_r = NULL;
1146 int nsamples = samp/ft->signal.channels;
1147 int i,j;
1148 int written = 0;
1149 SOX_SAMPLE_LOCALS;
1151 new_buffer_size = samp * sizeof(float);
1152 if (p->pcm_buffer_size < new_buffer_size) {
1153 float *new_buffer = lsx_realloc(p->pcm_buffer, new_buffer_size);
1154 if (!new_buffer) {
1155 lsx_fail_errno(ft, SOX_ENOMEM, "Out of memory");
1156 return 0;
1158 p->pcm_buffer_size = new_buffer_size;
1159 p->pcm_buffer = new_buffer;
1162 buffer_l = p->pcm_buffer;
1164 if (p->mp2)
1166 size_t s;
1167 for(s = 0; s < samp; s++)
1168 buffer_l[s] = SOX_SAMPLE_TO_FLOAT_32BIT(buf[s],);
1170 else
1172 if (ft->signal.channels == 2)
1174 /* lame doesn't support interleaved samples for floats so we must break
1175 * them out into seperate buffers.
1177 buffer_r = p->pcm_buffer + nsamples;
1178 j=0;
1179 for (i = 0; i < nsamples; i++)
1181 buffer_l[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1182 buffer_r[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1185 else
1187 j=0;
1188 for (i = 0; i < nsamples; i++) {
1189 buffer_l[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1194 new_buffer_size = LAME_BUFFER_SIZE(nsamples);
1195 if (p->mp3_buffer_size < new_buffer_size) {
1196 unsigned char *new_buffer = lsx_realloc(p->mp3_buffer, new_buffer_size);
1197 if (!new_buffer) {
1198 lsx_fail_errno(ft, SOX_ENOMEM, "Out of memory");
1199 return 0;
1201 p->mp3_buffer_size = new_buffer_size;
1202 p->mp3_buffer = new_buffer;
1205 if(p->mp2) {
1206 #ifdef HAVE_TWOLAME
1207 written = p->twolame_encode_buffer_float32_interleaved(p->opt, buffer_l,
1208 nsamples, p->mp3_buffer, (int)p->mp3_buffer_size);
1209 #endif
1210 } else {
1211 #ifdef HAVE_LAME
1212 written = p->lame_encode_buffer_float(p->gfp, buffer_l, buffer_r,
1213 nsamples, p->mp3_buffer, (int)p->mp3_buffer_size);
1214 #endif
1216 if (written < 0) {
1217 lsx_fail_errno(ft,SOX_EOF,"Encoding failed");
1218 return 0;
1221 if (lsx_writebuf(ft, p->mp3_buffer, (size_t)written) < (size_t)written)
1223 lsx_fail_errno(ft,SOX_EOF,"File write failed");
1224 return 0;
1227 return samp;
1230 static int stopwrite(sox_format_t * ft)
1232 priv_t *p = (priv_t *) ft->priv;
1233 uint64_t num_samples = ft->olength == SOX_IGNORE_LENGTH ? 0 : ft->olength / max(ft->signal.channels, 1);
1234 int written = 0;
1236 if (p->mp2) {
1237 #ifdef HAVE_TWOLAME
1238 written = p->twolame_encode_flush(p->opt, p->mp3_buffer, (int)p->mp3_buffer_size);
1239 #endif
1240 } else {
1241 #ifdef HAVE_LAME
1242 written = p->lame_encode_flush(p->gfp, p->mp3_buffer, (int)p->mp3_buffer_size);
1243 #endif
1245 if (written < 0)
1246 lsx_fail_errno(ft, SOX_EOF, "Encoding failed");
1247 else if (lsx_writebuf(ft, p->mp3_buffer, (size_t)written) < (size_t)written)
1248 lsx_fail_errno(ft, SOX_EOF, "File write failed");
1249 else if (!p->mp2) {
1250 #ifdef HAVE_LAME
1251 if (ft->seekable && (num_samples != p->num_samples || p->vbr_tag))
1252 rewrite_tags(ft, num_samples);
1253 #endif
1256 free(p->mp3_buffer);
1257 free(p->pcm_buffer);
1259 if(p->mp2) {
1260 #ifdef HAVE_TWOLAME
1261 p->twolame_close(&p->opt);
1262 LSX_DLLIBRARY_CLOSE(p, twolame_dl);
1263 #endif
1264 } else {
1265 #ifdef HAVE_LAME
1266 p->lame_close(p->gfp);
1267 LSX_DLLIBRARY_CLOSE(p, lame_dl);
1268 #endif
1270 return SOX_SUCCESS;
1273 #else /* !(HAVE_LAME || HAVE_TWOLAME) */
1274 static int startwrite(sox_format_t * ft UNUSED)
1276 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled with neither MP2 nor MP3 encoding support");
1277 return SOX_EOF;
1279 #define sox_mp3write NULL
1280 #define stopwrite NULL
1281 #endif /* HAVE_LAME || HAVE_TWOLAME */
1283 LSX_FORMAT_HANDLER(mp3)
1285 static char const * const names[] = {"mp3", "mp2", "audio/mpeg", NULL};
1286 static unsigned const write_encodings[] = {
1287 SOX_ENCODING_MP3, 0, 0};
1288 static sox_rate_t const write_rates[] = {
1289 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 0};
1290 static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
1291 "MPEG Layer 2/3 lossy audio compression", names, 0,
1292 startread, sox_mp3read, stopread,
1293 startwrite, sox_mp3write, stopwrite,
1294 sox_mp3seek, write_encodings, write_rates, sizeof(priv_t)
1296 return &handler;
1298 #endif /* defined(HAVE_MAD_H) || defined(HAVE_LAME) || defined(HAVE_TWOLAME) */