id3: fix COMM frame handling
[sox.git] / src / mp3.c
blob9fe707c377b54bea6208986a0bc716fdd2044409
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 #include "id3.h"
49 #if defined(HAVE_UNISTD_H)
50 #include <unistd.h>
51 #elif defined(HAVE_IO_H)
52 #include <io.h>
53 #endif
54 #else
55 #define ID3_TAG_FLAG_FOOTERPRESENT 0x10
56 #endif
58 #ifdef HAVE_TWOLAME_H
59 #include <twolame.h>
60 #endif
62 /* Under Windows, importing data from DLLs is a dicey proposition. This is true
63 * when using dlopen, but also true if linking directly against the DLL if the
64 * header does not mark the data as __declspec(dllexport), which mad.h does not.
65 * Sidestep the issue by defining our own mad_timer_zero. This is needed because
66 * mad_timer_zero is used in some of the mad.h macros.
68 #ifdef HAVE_MAD_H
69 #define mad_timer_zero mad_timer_zero_stub
70 static mad_timer_t const mad_timer_zero_stub = {0, 0};
71 #endif
73 #define MAXFRAMESIZE 2880
74 #define ID3PADDING 128
76 /* LAME takes float values as input. */
77 #define MP3_LAME_PRECISION 24
79 /* MAD returns values with MAD_F_FRACBITS (28) bits of precision, though it's
80 not certain that all of them are meaningful. Default to 16 bits to
81 align with most users expectation of output file should be 16 bits. */
82 #define MP3_MAD_PRECISION 16
84 static const char* const mad_library_names[] =
86 #ifdef DL_MAD
87 "libmad",
88 "libmad-0",
89 "cygmad-0",
90 #endif
91 NULL
94 #ifdef DL_MAD
95 #define MAD_FUNC LSX_DLENTRY_DYNAMIC
96 #else
97 #define MAD_FUNC LSX_DLENTRY_STATIC
98 #endif
100 #define MAD_FUNC_ENTRIES(f,x) \
101 MAD_FUNC(f,x, void, mad_stream_buffer, (struct mad_stream *, unsigned char const *, unsigned long)) \
102 MAD_FUNC(f,x, void, mad_stream_skip, (struct mad_stream *, unsigned long)) \
103 MAD_FUNC(f,x, int, mad_stream_sync, (struct mad_stream *)) \
104 MAD_FUNC(f,x, void, mad_stream_init, (struct mad_stream *)) \
105 MAD_FUNC(f,x, void, mad_frame_init, (struct mad_frame *)) \
106 MAD_FUNC(f,x, void, mad_synth_init, (struct mad_synth *)) \
107 MAD_FUNC(f,x, int, mad_frame_decode, (struct mad_frame *, struct mad_stream *)) \
108 MAD_FUNC(f,x, void, mad_timer_add, (mad_timer_t *, mad_timer_t)) \
109 MAD_FUNC(f,x, void, mad_synth_frame, (struct mad_synth *, struct mad_frame const *)) \
110 MAD_FUNC(f,x, char const *, mad_stream_errorstr, (struct mad_stream const *)) \
111 MAD_FUNC(f,x, void, mad_frame_finish, (struct mad_frame *)) \
112 MAD_FUNC(f,x, void, mad_stream_finish, (struct mad_stream *)) \
113 MAD_FUNC(f,x, unsigned long, mad_bit_read, (struct mad_bitptr *, unsigned int)) \
114 MAD_FUNC(f,x, int, mad_header_decode, (struct mad_header *, struct mad_stream *)) \
115 MAD_FUNC(f,x, void, mad_header_init, (struct mad_header *)) \
116 MAD_FUNC(f,x, signed long, mad_timer_count, (mad_timer_t, enum mad_units)) \
117 MAD_FUNC(f,x, void, mad_timer_multiply, (mad_timer_t *, signed long))
119 static const char* const lame_library_names[] =
121 #ifdef DL_LAME
122 "libmp3lame",
123 "libmp3lame-0",
124 "lame-enc",
125 "cygmp3lame-0",
126 #endif
127 NULL
130 #ifdef DL_LAME
131 #define LAME_FUNC LSX_DLENTRY_DYNAMIC
132 #else /* DL_LAME */
133 #define LAME_FUNC LSX_DLENTRY_STATIC
134 #endif /* DL_LAME */
136 #define LAME_FUNC_ENTRIES(f,x) \
137 LAME_FUNC(f,x, lame_global_flags*, lame_init, (void)) \
138 LAME_FUNC(f,x, int, lame_set_errorf, (lame_global_flags *, void (*)(const char *, va_list))) \
139 LAME_FUNC(f,x, int, lame_set_debugf, (lame_global_flags *, void (*)(const char *, va_list))) \
140 LAME_FUNC(f,x, int, lame_set_msgf, (lame_global_flags *, void (*)(const char *, va_list))) \
141 LAME_FUNC(f,x, int, lame_set_num_samples, (lame_global_flags *, unsigned long)) \
142 LAME_FUNC(f,x, int, lame_get_num_channels, (const lame_global_flags *)) \
143 LAME_FUNC(f,x, int, lame_set_num_channels, (lame_global_flags *, int)) \
144 LAME_FUNC(f,x, int, lame_set_in_samplerate, (lame_global_flags *, int)) \
145 LAME_FUNC(f,x, int, lame_set_out_samplerate, (lame_global_flags *, int)) \
146 LAME_FUNC(f,x, int, lame_set_bWriteVbrTag, (lame_global_flags *, int)) \
147 LAME_FUNC(f,x, int, lame_set_brate, (lame_global_flags *, int)) \
148 LAME_FUNC(f,x, int, lame_set_quality, (lame_global_flags *, int)) \
149 LAME_FUNC(f,x, vbr_mode, lame_get_VBR, (const lame_global_flags *)) \
150 LAME_FUNC(f,x, int, lame_set_VBR, (lame_global_flags *, vbr_mode)) \
151 LAME_FUNC(f,x, int, lame_set_VBR_q, (lame_global_flags *, int)) \
152 LAME_FUNC(f,x, int, lame_init_params, (lame_global_flags *)) \
153 LAME_FUNC(f,x, int, lame_encode_buffer_float, (lame_global_flags *, const float[], const float[], const int, unsigned char *, const int)) \
154 LAME_FUNC(f,x, int, lame_encode_flush, (lame_global_flags *, unsigned char *, int)) \
155 LAME_FUNC(f,x, int, lame_close, (lame_global_flags *)) \
156 LAME_FUNC(f,x, size_t, lame_get_lametag_frame, (const lame_global_flags *, unsigned char*, size_t)) \
157 LAME_FUNC(f,x, void, id3tag_init, (lame_global_flags *)) \
158 LAME_FUNC(f,x, void, id3tag_set_title, (lame_global_flags *, const char* title)) \
159 LAME_FUNC(f,x, void, id3tag_set_artist, (lame_global_flags *, const char* artist)) \
160 LAME_FUNC(f,x, void, id3tag_set_album, (lame_global_flags *, const char* album)) \
161 LAME_FUNC(f,x, void, id3tag_set_year, (lame_global_flags *, const char* year)) \
162 LAME_FUNC(f,x, void, id3tag_set_comment, (lame_global_flags *, const char* comment)) \
163 LAME_FUNC(f,x, int, id3tag_set_track, (lame_global_flags *, const char* track)) \
164 LAME_FUNC(f,x, int, id3tag_set_genre, (lame_global_flags *, const char* genre)) \
165 LAME_FUNC(f,x, size_t, id3tag_set_pad, (lame_global_flags *, size_t)) \
166 LAME_FUNC(f,x, size_t, lame_get_id3v2_tag, (lame_global_flags *, unsigned char*, size_t)) \
167 LAME_FUNC(f,x, int, id3tag_set_fieldvalue, (lame_global_flags *, const char *))
169 #ifdef HAVE_TWOLAME
170 static const char* const twolame_library_names[] =
172 #ifdef DL_TWOLAME
173 "libtwolame",
174 "libtwolame-0",
175 #endif
176 NULL
178 #endif
180 #ifdef DL_TWOLAME
181 #define TWOLAME_FUNC LSX_DLENTRY_DYNAMIC
182 #else
183 #define TWOLAME_FUNC LSX_DLENTRY_STATIC
184 #endif
186 #define TWOLAME_FUNC_ENTRIES(f,x) \
187 TWOLAME_FUNC(f,x, twolame_options*, twolame_init, (void)) \
188 TWOLAME_FUNC(f,x, int, twolame_get_num_channels, (twolame_options*)) \
189 TWOLAME_FUNC(f,x, int, twolame_set_num_channels, (twolame_options*, int)) \
190 TWOLAME_FUNC(f,x, int, twolame_set_in_samplerate, (twolame_options *, int)) \
191 TWOLAME_FUNC(f,x, int, twolame_set_out_samplerate, (twolame_options *, int)) \
192 TWOLAME_FUNC(f,x, int, twolame_set_brate, (twolame_options *, int)) \
193 TWOLAME_FUNC(f,x, int, twolame_init_params, (twolame_options *)) \
194 TWOLAME_FUNC(f,x, int, twolame_encode_buffer_float32_interleaved, (twolame_options *, const float [], int, unsigned char *, int)) \
195 TWOLAME_FUNC(f,x, int, twolame_encode_flush, (twolame_options *, unsigned char *, int)) \
196 TWOLAME_FUNC(f,x, void, twolame_close, (twolame_options **))
198 /* Private data */
199 typedef struct mp3_priv_t {
200 unsigned char *mp3_buffer;
201 size_t mp3_buffer_size;
203 #ifdef HAVE_MAD_H
204 struct mad_stream Stream;
205 struct mad_frame Frame;
206 struct mad_synth Synth;
207 mad_timer_t Timer;
208 ptrdiff_t cursamp;
209 size_t FrameCount;
210 LSX_DLENTRIES_TO_PTRS(MAD_FUNC_ENTRIES, mad_dl);
211 #endif /*HAVE_MAD_H*/
213 #if defined(HAVE_LAME) || defined(HAVE_TWOLAME)
214 float *pcm_buffer;
215 size_t pcm_buffer_size;
216 char mp2;
217 #endif
219 #ifdef HAVE_LAME
220 lame_global_flags *gfp;
221 uint64_t num_samples;
222 int vbr_tag;
223 LSX_DLENTRIES_TO_PTRS(LAME_FUNC_ENTRIES, lame_dl);
224 #endif
226 #ifdef HAVE_TWOLAME
227 twolame_options *opt;
228 LSX_DLENTRIES_TO_PTRS(TWOLAME_FUNC_ENTRIES, twolame_dl);
229 #endif
230 } priv_t;
232 #ifdef HAVE_MAD_H
234 /* This function merges the functions tagtype() and id3_tag_query()
235 from MAD's libid3tag, so we don't have to link to it
236 Returns 0 if the frame is not an ID3 tag, tag length if it is */
238 static int tagtype(const unsigned char *data, size_t length)
240 if (length >= 3 && data[0] == 'T' && data[1] == 'A' && data[2] == 'G')
242 return 128; /* ID3V1 */
245 if (length >= 10 &&
246 (data[0] == 'I' && data[1] == 'D' && data[2] == '3') &&
247 data[3] < 0xff && data[4] < 0xff &&
248 data[6] < 0x80 && data[7] < 0x80 && data[8] < 0x80 && data[9] < 0x80)
249 { /* ID3V2 */
250 unsigned char flags;
251 unsigned int size;
252 flags = data[5];
253 size = 10 + (data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9];
254 if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
255 size += 10;
256 for (; size < length && !data[size]; ++size); /* Consume padding */
257 return size;
260 return 0;
263 #endif /*HAVE_MAD_H*/
265 #include "mp3-util.h"
267 #ifdef HAVE_MAD_H
270 * (Re)fill the stream buffer that is to be decoded. If any data
271 * still exists in the buffer then they are first shifted to be
272 * front of the stream buffer.
274 static int sox_mp3_input(sox_format_t * ft)
276 priv_t *p = (priv_t *) ft->priv;
277 size_t bytes_read;
278 size_t remaining;
280 remaining = p->Stream.bufend - p->Stream.next_frame;
282 /* libmad does not consume all the buffer it's given. Some
283 * data, part of a truncated frame, is left unused at the
284 * end of the buffer. That data must be put back at the
285 * beginning of the buffer and taken in account for
286 * refilling the buffer. This means that the input buffer
287 * must be large enough to hold a complete frame at the
288 * highest observable bit-rate (currently 448 kb/s).
289 * TODO: Is 2016 bytes the size of the largest frame?
290 * (448000*(1152/32000))/8
292 memmove(p->mp3_buffer, p->Stream.next_frame, remaining);
294 bytes_read = lsx_readbuf(ft, p->mp3_buffer+remaining,
295 p->mp3_buffer_size-remaining);
296 if (bytes_read == 0)
298 return SOX_EOF;
301 p->mad_stream_buffer(&p->Stream, p->mp3_buffer, bytes_read+remaining);
302 p->Stream.error = 0;
304 return SOX_SUCCESS;
307 /* Attempts to read an ID3 tag at the current location in stream and
308 * consume it all. Returns SOX_EOF if no tag is found. Its up to
309 * caller to recover.
310 * */
311 static int sox_mp3_inputtag(sox_format_t * ft)
313 priv_t *p = (priv_t *) ft->priv;
314 int rc = SOX_EOF;
315 size_t remaining;
316 size_t tagsize;
319 /* FIXME: This needs some more work if we are to ever
320 * look at the ID3 frame. This is because the Stream
321 * may not be able to hold the complete ID3 frame.
322 * We should consume the whole frame inside tagtype()
323 * instead of outside of tagframe(). That would support
324 * recovering when Stream contains less then 8-bytes (header)
325 * and also when ID3v2 is bigger then Stream buffer size.
326 * Need to pass in stream so that buffer can be
327 * consumed as well as letting additional data to be
328 * read in.
330 remaining = p->Stream.bufend - p->Stream.next_frame;
331 if ((tagsize = tagtype(p->Stream.this_frame, remaining)))
333 p->mad_stream_skip(&p->Stream, tagsize);
334 rc = SOX_SUCCESS;
337 /* We know that a valid frame hasn't been found yet
338 * so help libmad out and go back into frame seek mode.
339 * This is true whether an ID3 tag was found or not.
341 p->mad_stream_sync(&p->Stream);
343 return rc;
346 static sox_bool sox_mp3_vbrtag(sox_format_t *ft)
348 priv_t *p = ft->priv;
349 struct mad_bitptr *anc = &p->Stream.anc_ptr;
351 if (p->Frame.header.layer != MAD_LAYER_III)
352 return sox_false;
354 if (p->Stream.anc_bitlen < 32)
355 return sox_false;
357 if (!memcmp(anc->byte, "Xing", 4) ||
358 !memcmp(anc->byte, "Info", 4))
359 return sox_true;
361 return sox_false;
364 static int startread(sox_format_t * ft)
366 priv_t *p = (priv_t *) ft->priv;
367 size_t ReadSize;
368 sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
369 int open_library_result;
371 LSX_DLLIBRARY_OPEN(
373 mad_dl,
374 MAD_FUNC_ENTRIES,
375 "MAD decoder library",
376 mad_library_names,
377 open_library_result);
378 if (open_library_result)
379 return SOX_EOF;
381 p->mp3_buffer_size = sox_globals.bufsiz;
382 p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);
384 ft->signal.length = SOX_UNSPEC;
385 if (ft->seekable) {
386 #ifdef USING_ID3TAG
387 lsx_id3_read_tag(ft, sox_true);
388 lsx_rewind(ft);
389 if (!ft->signal.length)
390 #endif
391 if (!ignore_length)
392 ft->signal.length = mp3_duration(ft);
395 p->mad_stream_init(&p->Stream);
396 p->mad_frame_init(&p->Frame);
397 p->mad_synth_init(&p->Synth);
398 mad_timer_reset(&p->Timer);
400 ft->encoding.encoding = SOX_ENCODING_MP3;
402 /* Decode at least one valid frame to find out the input
403 * format. The decoded frame will be saved off so that it
404 * can be processed later.
406 ReadSize = lsx_readbuf(ft, p->mp3_buffer, p->mp3_buffer_size);
407 if (ReadSize != p->mp3_buffer_size && lsx_error(ft))
408 return SOX_EOF;
410 p->mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);
412 /* Find a valid frame before starting up. This makes sure
413 * that we have a valid MP3 and also skips past ID3v2 tags
414 * at the beginning of the audio file.
416 p->Stream.error = 0;
417 while (p->mad_frame_decode(&p->Frame,&p->Stream))
419 /* check whether input buffer needs a refill */
420 if (p->Stream.error == MAD_ERROR_BUFLEN)
422 if (sox_mp3_input(ft) == SOX_EOF)
423 return SOX_EOF;
425 continue;
428 /* Consume any ID3 tags */
429 sox_mp3_inputtag(ft);
431 /* FIXME: We should probably detect when we've read
432 * a bunch of non-ID3 data and still haven't found a
433 * frame. In that case we can abort early without
434 * scanning the whole file.
436 p->Stream.error = 0;
439 if (p->Stream.error)
441 lsx_fail_errno(ft,SOX_EOF,"No valid MP3 frame found");
442 return SOX_EOF;
445 switch(p->Frame.header.mode)
447 case MAD_MODE_SINGLE_CHANNEL:
448 case MAD_MODE_DUAL_CHANNEL:
449 case MAD_MODE_JOINT_STEREO:
450 case MAD_MODE_STEREO:
451 ft->signal.channels = MAD_NCHANNELS(&p->Frame.header);
452 break;
453 default:
454 lsx_fail_errno(ft, SOX_EFMT, "Cannot determine number of channels");
455 return SOX_EOF;
458 ft->signal.precision = MP3_MAD_PRECISION;
459 ft->signal.rate=p->Frame.header.samplerate;
460 if (ignore_length)
461 ft->signal.length = SOX_UNSPEC;
462 else {
463 ft->signal.length *= ft->signal.channels; /* Keep separate from line above! */
466 if (!sox_mp3_vbrtag(ft))
467 p->Stream.next_frame = p->Stream.this_frame;
469 p->mad_frame_init(&p->Frame);
470 sox_mp3_input(ft);
472 p->cursamp = 0;
474 return SOX_SUCCESS;
478 * Read up to len samples from p->Synth
479 * If needed, read some more MP3 data, decode them and synth them
480 * Place in buf[].
481 * Return number of samples read.
483 static size_t sox_mp3read(sox_format_t * ft, sox_sample_t *buf, size_t len)
485 priv_t *p = (priv_t *) ft->priv;
486 size_t donow,i,done=0;
487 mad_fixed_t sample;
488 size_t chan;
490 do {
491 size_t x = (p->Synth.pcm.length - p->cursamp)*ft->signal.channels;
492 donow=min(len, x);
493 i=0;
494 while(i<donow){
495 for(chan=0;chan<ft->signal.channels;chan++){
496 sample=p->Synth.pcm.samples[chan][p->cursamp];
497 if (sample < -MAD_F_ONE)
498 sample=-MAD_F_ONE;
499 else if (sample >= MAD_F_ONE)
500 sample=MAD_F_ONE-1;
501 *buf++=(sox_sample_t)(sample<<(32-1-MAD_F_FRACBITS));
502 i++;
504 p->cursamp++;
507 len-=donow;
508 done+=donow;
510 if (len==0) break;
512 /* check whether input buffer needs a refill */
513 if (p->Stream.error == MAD_ERROR_BUFLEN)
515 if (sox_mp3_input(ft) == SOX_EOF) {
516 lsx_debug("sox_mp3_input EOF");
517 break;
521 if (p->mad_frame_decode(&p->Frame,&p->Stream))
523 if(MAD_RECOVERABLE(p->Stream.error))
525 sox_mp3_inputtag(ft);
526 continue;
528 else
530 if (p->Stream.error == MAD_ERROR_BUFLEN)
531 continue;
532 else
534 lsx_report("unrecoverable frame level error (%s).",
535 p->mad_stream_errorstr(&p->Stream));
536 break;
540 p->FrameCount++;
541 p->mad_timer_add(&p->Timer,p->Frame.header.duration);
542 p->mad_synth_frame(&p->Synth,&p->Frame);
543 p->cursamp=0;
544 } while(1);
546 return done;
549 static int stopread(sox_format_t * ft)
551 priv_t *p=(priv_t*) ft->priv;
553 mad_synth_finish(&p->Synth);
554 p->mad_frame_finish(&p->Frame);
555 p->mad_stream_finish(&p->Stream);
557 free(p->mp3_buffer);
558 LSX_DLLIBRARY_CLOSE(p, mad_dl);
559 return SOX_SUCCESS;
562 static int sox_mp3seek(sox_format_t * ft, uint64_t offset)
564 priv_t * p = (priv_t *) ft->priv;
565 size_t initial_bitrate = p->Frame.header.bitrate;
566 size_t tagsize = 0, consumed = 0;
567 sox_bool vbr = sox_false; /* Variable Bit Rate */
568 sox_bool depadded = sox_false;
569 uint64_t to_skip_samples = 0;
571 /* Reset all */
572 lsx_rewind(ft);
573 mad_timer_reset(&p->Timer);
574 p->FrameCount = 0;
576 /* They where opened in startread */
577 mad_synth_finish(&p->Synth);
578 p->mad_frame_finish(&p->Frame);
579 p->mad_stream_finish(&p->Stream);
581 p->mad_stream_init(&p->Stream);
582 p->mad_frame_init(&p->Frame);
583 p->mad_synth_init(&p->Synth);
585 offset /= ft->signal.channels;
586 to_skip_samples = offset;
588 while(sox_true) { /* Read data from the MP3 file */
589 size_t padding = 0;
590 size_t read;
591 size_t leftover = p->Stream.bufend - p->Stream.next_frame;
593 memmove(p->mp3_buffer, p->Stream.this_frame, leftover);
594 read = lsx_readbuf(ft, p->mp3_buffer + leftover, p->mp3_buffer_size - leftover);
595 if (read == 0) {
596 lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover);
597 break;
599 for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding);
600 depadded = sox_true;
601 p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding);
603 while (sox_true) { /* Decode frame headers */
604 static unsigned short samples;
605 p->Stream.error = MAD_ERROR_NONE;
607 /* Not an audio frame */
608 if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) {
609 if (p->Stream.error == MAD_ERROR_BUFLEN)
610 break; /* Normal behaviour; get some more data from the file */
611 if (!MAD_RECOVERABLE(p->Stream.error)) {
612 lsx_warn("unrecoverable MAD error");
613 break;
615 if (p->Stream.error == MAD_ERROR_LOSTSYNC) {
616 unsigned available = (p->Stream.bufend - p->Stream.this_frame);
617 tagsize = tagtype(p->Stream.this_frame, (size_t) available);
618 if (tagsize) { /* It's some ID3 tags, so just skip */
619 if (tagsize >= available) {
620 lsx_seeki(ft, (off_t)(tagsize - available), SEEK_CUR);
621 depadded = sox_false;
623 p->mad_stream_skip(&p->Stream, min(tagsize, available));
625 else lsx_warn("MAD lost sync");
627 else lsx_warn("recoverable MAD error");
628 continue;
631 consumed += p->Stream.next_frame - p->Stream.this_frame;
632 vbr |= (p->Frame.header.bitrate != initial_bitrate);
634 samples = 32 * MAD_NSBSAMPLES(&p->Frame.header);
636 p->FrameCount++;
637 p->mad_timer_add(&p->Timer, p->Frame.header.duration);
639 if(to_skip_samples <= samples)
641 p->mad_frame_decode(&p->Frame,&p->Stream);
642 p->mad_synth_frame(&p->Synth, &p->Frame);
643 p->cursamp = to_skip_samples;
644 return SOX_SUCCESS;
646 else to_skip_samples -= samples;
648 /* If not VBR, we can extrapolate frame size */
649 if (p->FrameCount == 64 && !vbr) {
650 p->FrameCount = offset / samples;
651 to_skip_samples = offset % samples;
653 if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET))
654 return SOX_EOF;
656 /* Reset Stream for refilling buffer */
657 p->mad_stream_finish(&p->Stream);
658 p->mad_stream_init(&p->Stream);
659 break;
664 return SOX_EOF;
666 #else /* !HAVE_MAD_H */
667 static int startread(sox_format_t * ft)
669 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP3 decoding support");
670 return SOX_EOF;
672 #define sox_mp3read NULL
673 #define stopread NULL
674 #define sox_mp3seek NULL
675 #endif /*HAVE_MAD_H*/
677 #ifdef HAVE_LAME
679 /* Adapters for lame message callbacks: */
681 static void errorf(const char* fmt, va_list va)
683 sox_globals.subsystem=__FILE__;
684 if (sox_globals.output_message_handler)
685 (*sox_globals.output_message_handler)(1,sox_globals.subsystem,fmt,va);
686 return;
689 static void debugf(const char* fmt, va_list va)
691 sox_globals.subsystem=__FILE__;
692 if (sox_globals.output_message_handler)
693 (*sox_globals.output_message_handler)(4,sox_globals.subsystem,fmt,va);
694 return;
697 static void msgf(const char* fmt, va_list va)
699 sox_globals.subsystem=__FILE__;
700 if (sox_globals.output_message_handler)
701 (*sox_globals.output_message_handler)(3,sox_globals.subsystem,fmt,va);
702 return;
705 /* These functions are considered optional. If they aren't present in the
706 library, the stub versions defined here will be used instead. */
708 UNUSED static void id3tag_init_stub(lame_global_flags * gfp UNUSED)
709 { return; }
710 UNUSED static void id3tag_set_title_stub(lame_global_flags * gfp UNUSED, const char* title UNUSED)
711 { return; }
712 UNUSED static void id3tag_set_artist_stub(lame_global_flags * gfp UNUSED, const char* artist UNUSED)
713 { return; }
714 UNUSED static void id3tag_set_album_stub(lame_global_flags * gfp UNUSED, const char* album UNUSED)
715 { return; }
716 UNUSED static void id3tag_set_year_stub(lame_global_flags * gfp UNUSED, const char* year UNUSED)
717 { return; }
718 UNUSED static void id3tag_set_comment_stub(lame_global_flags * gfp UNUSED, const char* comment UNUSED)
719 { return; }
720 UNUSED static void id3tag_set_track_stub(lame_global_flags * gfp UNUSED, const char* track UNUSED)
721 { return; }
722 UNUSED static int id3tag_set_genre_stub(lame_global_flags * gfp UNUSED, const char* genre UNUSED)
723 { return 0; }
724 UNUSED static size_t id3tag_set_pad_stub(lame_global_flags * gfp UNUSED, size_t n UNUSED)
725 { return 0; }
726 UNUSED static size_t lame_get_id3v2_tag_stub(lame_global_flags * gfp UNUSED, unsigned char * buffer UNUSED, size_t size UNUSED)
727 { return 0; }
728 UNUSED static int id3tag_set_fieldvalue_stub(lame_global_flags * gfp UNUSED, const char *fieldvalue UNUSED)
729 { return 0; }
731 static int get_id3v2_tag_size(sox_format_t * ft)
733 size_t bytes_read;
734 int id3v2_size;
735 unsigned char id3v2_header[10];
737 if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0) {
738 lsx_warn("cannot update id3 tag - failed to seek to beginning");
739 return SOX_EOF;
742 /* read 10 bytes in case there's an ID3 version 2 header here */
743 bytes_read = lsx_readbuf(ft, id3v2_header, sizeof(id3v2_header));
744 if (bytes_read != sizeof(id3v2_header)) {
745 lsx_warn("cannot update id3 tag - failed to read id3 header");
746 return SOX_EOF; /* not readable, maybe opened Write-Only */
749 /* does the stream begin with the ID3 version 2 file identifier? */
750 if (!strncmp((char *) id3v2_header, "ID3", (size_t)3)) {
751 /* the tag size (minus the 10-byte header) is encoded into four
752 * bytes where the most significant bit is clear in each byte */
753 id3v2_size = (((id3v2_header[6] & 0x7f) << 21)
754 | ((id3v2_header[7] & 0x7f) << 14)
755 | ((id3v2_header[8] & 0x7f) << 7)
756 | (id3v2_header[9] & 0x7f))
757 + sizeof(id3v2_header);
758 } else {
759 /* no ID3 version 2 tag in this stream */
760 id3v2_size = 0;
762 return id3v2_size;
765 static void rewrite_id3v2_tag(sox_format_t * ft, size_t id3v2_size, uint64_t num_samples)
767 priv_t *p = (priv_t *)ft->priv;
768 size_t new_size;
769 unsigned char * buffer;
771 if (LSX_DLFUNC_IS_STUB(p, lame_get_id3v2_tag))
773 if (p->num_samples)
774 lsx_warn("cannot update track length info - tag update not supported with this version of LAME. Track length will be incorrect.");
775 else
776 lsx_report("cannot update track length info - tag update not supported with this version of LAME. Track length will be unspecified.");
777 return;
780 buffer = lsx_malloc(id3v2_size);
781 if (!buffer)
783 lsx_warn("cannot update track length info - failed to allocate buffer");
784 return;
787 if (num_samples > ULONG_MAX)
789 lsx_warn("cannot accurately update track length info - file is too long");
790 num_samples = 0;
792 p->lame_set_num_samples(p->gfp, (unsigned long)num_samples);
793 lsx_debug("updated MP3 TLEN to %lu samples", (unsigned long)num_samples);
795 new_size = p->lame_get_id3v2_tag(p->gfp, buffer, id3v2_size);
797 if (new_size != id3v2_size && new_size-ID3PADDING <= id3v2_size) {
798 p->id3tag_set_pad(p->gfp, ID3PADDING + id3v2_size - new_size);
799 new_size = p->lame_get_id3v2_tag(p->gfp, buffer, id3v2_size);
802 if (new_size != id3v2_size) {
803 if (LSX_DLFUNC_IS_STUB(p, id3tag_set_pad))
805 if (p->num_samples)
806 lsx_warn("cannot update track length info - tag size adjustment not supported with this version of LAME. Track length will be invalid.");
807 else
808 lsx_report("cannot update track length info - tag size adjustment not supported with this version of LAME. Track length will be unspecified.");
810 else
811 lsx_warn("cannot update track length info - failed to adjust tag size");
812 } else {
813 lsx_seeki(ft, (off_t)0, SEEK_SET);
814 /* Overwrite the Id3v2 tag (this time TLEN should be accurate) */
815 if (lsx_writebuf(ft, buffer, id3v2_size) != 1) {
816 lsx_debug("Rewrote Id3v2 tag (%" PRIuPTR " bytes)", id3v2_size);
820 free(buffer);
823 static void rewrite_tags(sox_format_t * ft, uint64_t num_samples)
825 priv_t *p = (priv_t *)ft->priv;
827 off_t file_size;
828 size_t id3v2_size;
830 if (lsx_seeki(ft, (off_t)0, SEEK_END)) {
831 lsx_warn("cannot update tags - seek to end failed");
832 return;
835 /* Get file size */
836 file_size = lsx_tell(ft);
838 if (file_size == 0) {
839 lsx_warn("cannot update tags - file size is 0");
840 return;
843 id3v2_size = get_id3v2_tag_size(ft);
844 if (id3v2_size > 0 && num_samples != p->num_samples) {
845 rewrite_id3v2_tag(ft, id3v2_size, num_samples);
848 if (p->vbr_tag) {
849 size_t lametag_size;
850 uint8_t buffer[MAXFRAMESIZE];
852 if (lsx_seeki(ft, (off_t)id3v2_size, SEEK_SET)) {
853 lsx_warn("cannot write VBR tag - seek to tag block failed");
854 return;
857 lametag_size = p->lame_get_lametag_frame(p->gfp, buffer, sizeof(buffer));
858 if (lametag_size > sizeof(buffer)) {
859 lsx_warn("cannot write VBR tag - VBR tag too large for buffer");
860 return;
863 if (lametag_size < 1) {
864 return;
867 if (lsx_writebuf(ft, buffer, lametag_size) != lametag_size) {
868 lsx_warn("cannot write VBR tag - VBR tag write failed");
869 } else {
870 lsx_debug("rewrote VBR tag (%" PRIuPTR " bytes)", lametag_size);
875 #endif /* HAVE_LAME */
877 #if defined(HAVE_LAME) || defined(HAVE_TWOLAME)
879 #define LAME_BUFFER_SIZE(num_samples) (((num_samples) + 3) / 4 * 5 + 7200)
881 static int startwrite(sox_format_t * ft)
883 priv_t *p = (priv_t *) ft->priv;
884 int openlibrary_result;
885 int fail = 0;
887 if (ft->encoding.encoding != SOX_ENCODING_MP3) {
888 if(ft->encoding.encoding != SOX_ENCODING_UNKNOWN)
889 lsx_report("Encoding forced to MP2/MP3");
890 ft->encoding.encoding = SOX_ENCODING_MP3;
893 if(strchr(ft->filetype, '2'))
894 p->mp2 = 1;
896 if (p->mp2) {
897 #ifdef HAVE_TWOLAME
898 LSX_DLLIBRARY_OPEN(
900 twolame_dl,
901 TWOLAME_FUNC_ENTRIES,
902 "Twolame encoder library",
903 twolame_library_names,
904 openlibrary_result);
905 #else
906 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP2 encoding support");
907 return SOX_EOF;
908 #endif
909 } else {
910 #ifdef HAVE_LAME
911 LSX_DLLIBRARY_OPEN(
913 lame_dl,
914 LAME_FUNC_ENTRIES,
915 "LAME encoder library",
916 lame_library_names,
917 openlibrary_result);
918 #else
919 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled without MP3 encoding support");
920 return SOX_EOF;
921 #endif
923 if (openlibrary_result)
924 return SOX_EOF;
926 p->mp3_buffer_size = LAME_BUFFER_SIZE(sox_globals.bufsiz / max(ft->signal.channels, 1));
927 p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);
929 p->pcm_buffer_size = sox_globals.bufsiz * sizeof(float);
930 p->pcm_buffer = lsx_malloc(p->pcm_buffer_size);
932 if (p->mp2) {
933 #ifdef HAVE_TWOLAME
934 p->opt = p->twolame_init();
936 if (p->opt == NULL){
937 lsx_fail_errno(ft,SOX_EOF,"Initialization of Twolame library failed");
938 return(SOX_EOF);
940 #endif
941 } else {
942 #ifdef HAVE_LAME
943 p->gfp = p->lame_init();
945 if (p->gfp == NULL){
946 lsx_fail_errno(ft,SOX_EOF,"Initialization of LAME library failed");
947 return(SOX_EOF);
950 /* First set message callbacks so we don't miss any messages: */
951 p->lame_set_errorf(p->gfp,errorf);
952 p->lame_set_debugf(p->gfp,debugf);
953 p->lame_set_msgf (p->gfp,msgf);
955 p->num_samples = ft->signal.length == SOX_IGNORE_LENGTH ? 0 : ft->signal.length / max(ft->signal.channels, 1);
956 p->lame_set_num_samples(p->gfp, p->num_samples > ULONG_MAX ? 0 : (unsigned long)p->num_samples);
957 #endif
960 ft->signal.precision = MP3_LAME_PRECISION;
962 if (ft->signal.channels != SOX_ENCODING_UNKNOWN) {
963 if (p->mp2) {
964 #ifdef HAVE_TWOLAME
965 fail = (p->twolame_set_num_channels(p->opt,(int)ft->signal.channels) != 0);
966 #endif
967 } else {
968 #ifdef HAVE_LAME
969 fail = (p->lame_set_num_channels(p->gfp,(int)ft->signal.channels) < 0);
970 #endif
972 if (fail) {
973 lsx_fail_errno(ft,SOX_EOF,"Unsupported number of channels");
974 return(SOX_EOF);
977 else {
978 if (p->mp2) {
979 #ifdef HAVE_TWOLAME
980 ft->signal.channels = p->twolame_get_num_channels(p->opt); /* Twolame default */
981 #endif
982 } else {
983 #ifdef HAVE_LAME
984 ft->signal.channels = p->lame_get_num_channels(p->gfp); /* LAME default */
985 #endif
989 if (p->mp2) {
990 #ifdef HAVE_TWOLAME
991 p->twolame_set_in_samplerate(p->opt,(int)ft->signal.rate);
992 p->twolame_set_out_samplerate(p->opt,(int)ft->signal.rate);
993 #endif
994 } else {
995 #ifdef HAVE_LAME
996 p->lame_set_in_samplerate(p->gfp,(int)ft->signal.rate);
997 p->lame_set_out_samplerate(p->gfp,(int)ft->signal.rate);
998 #endif
1001 if (!p->mp2) {
1002 #ifdef HAVE_LAME
1003 if (!LSX_DLFUNC_IS_STUB(p, id3tag_init))
1004 write_comments(ft);
1005 #endif
1008 /* The primary parameter to the LAME encoder is the bit rate. If the
1009 * value of encoding.compression is a positive integer, it's taken as
1010 * the bitrate in kbps (that is if you specify 128, it use 128 kbps).
1012 * The second most important parameter is probably "quality" (really
1013 * performance), which allows balancing encoding speed vs. quality.
1014 * In LAME, 0 specifies highest quality but is very slow, while
1015 * 9 selects poor quality, but is fast. (5 is the default and 2 is
1016 * recommended as a good trade-off for high quality encodes.)
1018 * Because encoding.compression is a float, the fractional part is used
1019 * to select quality. 128.2 selects 128 kbps encoding with a quality
1020 * of 2. There is one problem with this approach. We need 128 to specify
1021 * 128 kbps encoding with default quality, so .0 means use default. Instead
1022 * of .0 you have to use .01 to specify the highest quality (128.01).
1024 * LAME uses bitrate to specify a constant bitrate, but higher quality
1025 * can be achieved using Variable Bit Rate (VBR). VBR quality (really
1026 * size) is selected using a number from 0 to 9. Use a value of 0 for high
1027 * quality, larger files, and 9 for smaller files of lower quality. 4 is
1028 * the default.
1030 * In order to squeeze the selection of VBR into the encoding.compression
1031 * float we use negative numbers to select VRR. -4.2 would select default
1032 * VBR encoding (size) with high quality (speed). One special case is 0,
1033 * which is a valid VBR encoding parameter but not a valid bitrate.
1034 * Compression value of 0 is always treated as a high quality vbr, as a
1035 * result both -0.2 and 0.2 are treated as highest quality VBR (size) and
1036 * high quality (speed).
1038 * Note: It would have been nice to simply use low values, 0-9, to trigger
1039 * VBR mode, but 8 kbps is a valid bit rate, so negative values were
1040 * used instead.
1043 lsx_debug("-C option is %f", ft->encoding.compression);
1045 if (ft->encoding.compression == HUGE_VAL) {
1046 /* Do nothing, use defaults: */
1047 lsx_report("using %s encoding defaults", p->mp2? "MP2" : "MP3");
1048 } else {
1049 double abs_compression = fabs(ft->encoding.compression);
1050 double floor_compression = floor(abs_compression);
1051 double fraction_compression = abs_compression - floor_compression;
1052 int bitrate_q = (int)floor_compression;
1053 int encoder_q =
1054 fraction_compression == 0.0
1055 ? -1
1056 : (int)(fraction_compression * 10.0 + 0.5);
1058 if (ft->encoding.compression < 0.5) {
1059 if (p->mp2) {
1060 lsx_fail_errno(ft,SOX_EOF,"Variable bitrate encoding not supported for MP2 audio");
1061 return(SOX_EOF);
1063 #ifdef HAVE_LAME
1064 if (p->lame_get_VBR(p->gfp) == vbr_off)
1065 p->lame_set_VBR(p->gfp, vbr_default);
1067 if (ft->seekable) {
1068 p->vbr_tag = 1;
1069 } else {
1070 lsx_warn("unable to write VBR tag because we can't seek");
1073 if (p->lame_set_VBR_q(p->gfp, bitrate_q) < 0)
1075 lsx_fail_errno(ft, SOX_EOF,
1076 "lame_set_VBR_q(%d) failed (should be between 0 and 9)",
1077 bitrate_q);
1078 return(SOX_EOF);
1080 lsx_report("lame_set_VBR_q(%d)", bitrate_q);
1081 #endif
1082 } else {
1083 if (p->mp2) {
1084 #ifdef HAVE_TWOLAME
1085 fail = (p->twolame_set_brate(p->opt, bitrate_q) != 0);
1086 #endif
1087 } else {
1088 #ifdef HAVE_LAME
1089 fail = (p->lame_set_brate(p->gfp, bitrate_q) < 0);
1090 #endif
1092 if (fail) {
1093 lsx_fail_errno(ft, SOX_EOF,
1094 "%slame_set_brate(%d) failed", p->mp2? "two" : "", bitrate_q);
1095 return(SOX_EOF);
1097 lsx_report("(two)lame_set_brate(%d)", bitrate_q);
1100 /* Set Quality */
1102 if (encoder_q < 0 || p->mp2) {
1103 /* use default quality value */
1104 lsx_report("using %s default quality", p->mp2? "MP2" : "MP3");
1105 } else {
1106 #ifdef HAVE_LAME
1107 if (p->lame_set_quality(p->gfp, encoder_q) < 0) {
1108 lsx_fail_errno(ft, SOX_EOF,
1109 "lame_set_quality(%d) failed", encoder_q);
1110 return(SOX_EOF);
1112 lsx_report("lame_set_quality(%d)", encoder_q);
1113 #endif
1117 if (!p->mp2) {
1118 #ifdef HAVE_LAME
1119 p->lame_set_bWriteVbrTag(p->gfp, p->vbr_tag);
1120 #endif
1123 if (p->mp2) {
1124 #ifdef HAVE_TWOLAME
1125 fail = (p->twolame_init_params(p->opt) != 0);
1126 #endif
1127 } else {
1128 #ifdef HAVE_LAME
1129 fail = (p->lame_init_params(p->gfp) < 0);
1130 #endif
1132 if (fail) {
1133 lsx_fail_errno(ft,SOX_EOF,"%s initialization failed", p->mp2? "Twolame" : "LAME");
1134 return(SOX_EOF);
1137 return(SOX_SUCCESS);
1140 #define MP3_SAMPLE_TO_FLOAT(d) ((float)(32768*SOX_SAMPLE_TO_FLOAT_32BIT(d,)))
1142 static size_t sox_mp3write(sox_format_t * ft, const sox_sample_t *buf, size_t samp)
1144 priv_t *p = (priv_t *)ft->priv;
1145 size_t new_buffer_size;
1146 float *buffer_l, *buffer_r = NULL;
1147 int nsamples = samp/ft->signal.channels;
1148 int i,j;
1149 int written = 0;
1150 SOX_SAMPLE_LOCALS;
1152 new_buffer_size = samp * sizeof(float);
1153 if (p->pcm_buffer_size < new_buffer_size) {
1154 float *new_buffer = lsx_realloc(p->pcm_buffer, new_buffer_size);
1155 if (!new_buffer) {
1156 lsx_fail_errno(ft, SOX_ENOMEM, "Out of memory");
1157 return 0;
1159 p->pcm_buffer_size = new_buffer_size;
1160 p->pcm_buffer = new_buffer;
1163 buffer_l = p->pcm_buffer;
1165 if (p->mp2)
1167 size_t s;
1168 for(s = 0; s < samp; s++)
1169 buffer_l[s] = SOX_SAMPLE_TO_FLOAT_32BIT(buf[s],);
1171 else
1173 if (ft->signal.channels == 2)
1175 /* lame doesn't support interleaved samples for floats so we must break
1176 * them out into seperate buffers.
1178 buffer_r = p->pcm_buffer + nsamples;
1179 j=0;
1180 for (i = 0; i < nsamples; i++)
1182 buffer_l[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1183 buffer_r[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1186 else
1188 j=0;
1189 for (i = 0; i < nsamples; i++) {
1190 buffer_l[i] = MP3_SAMPLE_TO_FLOAT(buf[j++]);
1195 new_buffer_size = LAME_BUFFER_SIZE(nsamples);
1196 if (p->mp3_buffer_size < new_buffer_size) {
1197 unsigned char *new_buffer = lsx_realloc(p->mp3_buffer, new_buffer_size);
1198 if (!new_buffer) {
1199 lsx_fail_errno(ft, SOX_ENOMEM, "Out of memory");
1200 return 0;
1202 p->mp3_buffer_size = new_buffer_size;
1203 p->mp3_buffer = new_buffer;
1206 if(p->mp2) {
1207 #ifdef HAVE_TWOLAME
1208 written = p->twolame_encode_buffer_float32_interleaved(p->opt, buffer_l,
1209 nsamples, p->mp3_buffer, (int)p->mp3_buffer_size);
1210 #endif
1211 } else {
1212 #ifdef HAVE_LAME
1213 written = p->lame_encode_buffer_float(p->gfp, buffer_l, buffer_r,
1214 nsamples, p->mp3_buffer, (int)p->mp3_buffer_size);
1215 #endif
1217 if (written < 0) {
1218 lsx_fail_errno(ft,SOX_EOF,"Encoding failed");
1219 return 0;
1222 if (lsx_writebuf(ft, p->mp3_buffer, (size_t)written) < (size_t)written)
1224 lsx_fail_errno(ft,SOX_EOF,"File write failed");
1225 return 0;
1228 return samp;
1231 static int stopwrite(sox_format_t * ft)
1233 priv_t *p = (priv_t *) ft->priv;
1234 uint64_t num_samples = ft->olength == SOX_IGNORE_LENGTH ? 0 : ft->olength / max(ft->signal.channels, 1);
1235 int written = 0;
1237 if (p->mp2) {
1238 #ifdef HAVE_TWOLAME
1239 written = p->twolame_encode_flush(p->opt, p->mp3_buffer, (int)p->mp3_buffer_size);
1240 #endif
1241 } else {
1242 #ifdef HAVE_LAME
1243 written = p->lame_encode_flush(p->gfp, p->mp3_buffer, (int)p->mp3_buffer_size);
1244 #endif
1246 if (written < 0)
1247 lsx_fail_errno(ft, SOX_EOF, "Encoding failed");
1248 else if (lsx_writebuf(ft, p->mp3_buffer, (size_t)written) < (size_t)written)
1249 lsx_fail_errno(ft, SOX_EOF, "File write failed");
1250 else if (!p->mp2) {
1251 #ifdef HAVE_LAME
1252 if (ft->seekable && (num_samples != p->num_samples || p->vbr_tag))
1253 rewrite_tags(ft, num_samples);
1254 #endif
1257 free(p->mp3_buffer);
1258 free(p->pcm_buffer);
1260 if(p->mp2) {
1261 #ifdef HAVE_TWOLAME
1262 p->twolame_close(&p->opt);
1263 LSX_DLLIBRARY_CLOSE(p, twolame_dl);
1264 #endif
1265 } else {
1266 #ifdef HAVE_LAME
1267 p->lame_close(p->gfp);
1268 LSX_DLLIBRARY_CLOSE(p, lame_dl);
1269 #endif
1271 return SOX_SUCCESS;
1274 #else /* !(HAVE_LAME || HAVE_TWOLAME) */
1275 static int startwrite(sox_format_t * ft UNUSED)
1277 lsx_fail_errno(ft,SOX_EOF,"SoX was compiled with neither MP2 nor MP3 encoding support");
1278 return SOX_EOF;
1280 #define sox_mp3write NULL
1281 #define stopwrite NULL
1282 #endif /* HAVE_LAME || HAVE_TWOLAME */
1284 LSX_FORMAT_HANDLER(mp3)
1286 static char const * const names[] = {"mp3", "mp2", "audio/mpeg", NULL};
1287 static unsigned const write_encodings[] = {
1288 SOX_ENCODING_MP3, 0, 0};
1289 static sox_rate_t const write_rates[] = {
1290 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 0};
1291 static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
1292 "MPEG Layer 2/3 lossy audio compression", names, 0,
1293 startread, sox_mp3read, stopread,
1294 startwrite, sox_mp3write, stopwrite,
1295 sox_mp3seek, write_encodings, write_rates, sizeof(priv_t)
1297 return &handler;
1299 #endif /* defined(HAVE_MAD_H) || defined(HAVE_LAME) || defined(HAVE_TWOLAME) */