Audacity 3.2.0
ImportMP3.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ImportMP3.cpp
6
7 Joshua Haberman
8 Leland Lucius
9
10*//****************************************************************//****************************************************************//*******************************************************************/
28
29
30
31#include <wx/defs.h>
32
33#include "Import.h"
34#include "BasicUI.h"
35#include "ImportPlugin.h"
36#include "Project.h"
37
38#define DESC XO("MP3 files")
39
40static const auto exts =
41{
42 wxT("mp3"),
43 wxT("mp2"),
44 wxT("mpa")
45};
46
47#ifndef USE_LIBMAD
48
50{
51 std::make_unique<UnusableImportPlugin>(DESC, FileExtensions(exts.begin(), exts.end()))
52};
53
54#else
55
56#if defined(__WXMSW__)
57#include <malloc.h>
58#else
59#include <stdlib.h>
60#endif
61
62#include <wx/file.h>
63#include <wx/string.h>
64
65#include "Prefs.h"
66#include "../Tags.h"
67#include "../WaveTrack.h"
68#include "../widgets/AudacityMessageBox.h"
69#include "../widgets/ProgressDialog.h"
70
71// PRL: include these last,
72// and correct some preprocessor namespace pollution from wxWidgets that
73// caused a warning about duplicate definition
74#undef SIZEOF_LONG
75extern "C"
76{
77#include "mad.h"
78
79#ifdef USE_LIBID3TAG
80#include <id3tag.h>
81#endif
82}
83
84// Specifies the number of bytes in the input buffer. This also controls
85// how many bytes will be scanned when searching for the first MP3 frame.
86#define INPUT_BUFFER_SIZE 65535
87
88// This is the number of decoded samples libmad adds at the beginning
89// (This is an "observed" value.)
90#define MAD_DELAY 529
91
92class MP3ImportPlugin final : public ImportPlugin
93{
94public:
97
98 wxString GetPluginStringID() override;
100 std::unique_ptr<ImportFileHandle> Open(const FilePath &Filename, AudacityProject*) override;
101};
102
103using NewChannelGroup = std::vector< std::shared_ptr<WaveTrack> >;
104
106{
107public:
108 MP3ImportFileHandle(const FilePath &filename);
110
113 ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override;
114 wxInt32 GetStreamCount() override;
115 const TranslatableStrings &GetStreamInfo() override;
116 void SetStreamUsage(wxInt32 StreamID, bool Use) override;
117
118private:
119 bool Open();
120 void CheckTags();
121 void CheckAPETags(bool atEnd);
122 void CheckID3V1Tags();
123 void CheckID3V2Tags(bool atEnd);
124 void CheckLyrics();
125 bool CheckMP3();
126 bool FillBuffer();
127 void LoadID3(Tags *tags);
128
129 // The MAD callbacks
130
131 static mad_flow input_cb(void *that,
132 struct mad_stream *stream);
133 mad_flow InputCB(struct mad_stream *stream);
134
135 static mad_flow filter_cb(void *that,
136 struct mad_stream const *stream,
137 struct mad_frame *frame);
138 mad_flow FilterCB(struct mad_stream const *stream, struct mad_frame *frame);
139
140 static mad_flow output_cb(void *that,
141 struct mad_header const *header,
142 struct mad_pcm *pcm);
143 mad_flow OutputCB(struct mad_header const *header, struct mad_pcm *pcm);
144
145 static mad_flow error_cb(void *that,
146 struct mad_stream *stream,
147 struct mad_frame *frame);
148 mad_flow ErrorCB(struct mad_stream *stream, struct mad_frame *frame);
149
150private:
152
153 wxFile mFile;
154 wxFileOffset mFilePos;
155 wxFileOffset mFileLen;
156
157 unsigned char mInputBuffer[INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
159
162 unsigned mNumChannels;
163
165
168
170
172};
173
174// ============================================================================
175// MP3ImportPlugin
176// ============================================================================
177
180{
181}
182
184{
185}
186
188{
189 return wxT("libmad");
190}
191
193{
194 return DESC;
195}
196
197std::unique_ptr<ImportFileHandle> MP3ImportPlugin::Open(
198 const FilePath &Filename, AudacityProject *)
199{
200 auto handle = std::make_unique<MP3ImportFileHandle>(Filename);
201
202 if (!handle->Open())
203 {
204 return nullptr;
205 }
206
207 return handle;
208}
209
211{
212 "MP3",
213 std::make_unique<MP3ImportPlugin>()
214};
215
216// ============================================================================
217// MP3ImportFileHandle
218// ============================================================================
219
221: ImportFileHandle(filename)
222{
223}
224
226{
227}
228
230{
231 return DESC;
232}
233
235{
236 // TODO
237 return 0;
238}
239
241{
242 return 1;
243}
244
246{
247 static TranslatableStrings empty;
248 return empty;
249}
250
251void MP3ImportFileHandle::SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use))
252{
253}
254
256 TrackHolders &outTracks,
257 Tags *tags)
258{
259 outTracks.clear();
260
262
263 mTrackFactory = trackFactory;
265 mNumChannels = 0;
266
267 // Set delay and padding to best possible in case the LAME tag is not present
269 mPadding = 0;
270
271 // Initialize decoder
272 mad_decoder_init(&mDecoder, this, input_cb, 0, filter_cb, output_cb, error_cb, 0);
273
274 // Send the decoder on its way!
275 auto res = mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC);
276
277 // Terminate decoder
278 mad_decoder_finish(&mDecoder);
279
280 // Decoding failed, so pass it on
281 if (res != 0)
282 {
283 return ProgressResult::Failed;
284 }
285
286 // The user canceled the decoding, so bail without saving tracks or tags
288 {
289 return mUpdateResult;
290 }
291
292 // Flush and trim the channels
293 for (const auto &channel : mChannels)
294 {
295 channel->Flush();
296
297 // Trim any padding
298 if (mPadding)
299 {
300 double et = channel->GetEndTime();
301 double t1 = et - channel->LongSamplesToTime(mPadding);
302 channel->Clear(t1, et);
303 }
304
305 // And delay
306 if (mDelay)
307 {
308 double st = channel->GetStartTime();
309 double t0 = st + channel->LongSamplesToTime(mDelay);
310 channel->Clear(st, t0);
311 }
312 }
313
314 // Copy the WaveTrack pointers into the Track pointer list that
315 // we are expected to fill
316 outTracks.push_back(std::move(mChannels));
317
318 // Load ID3 tags from the file
319 LoadID3(tags);
320
321 return mUpdateResult;
322}
323
325{
326 mInputBufferLen = 0;
327 mFilePos = 0;
328 mHaveID3 = false;
329
330 // Open the file
331 if (!mFile.Open(mFilename))
332 {
333 return false;
334 }
335
336 // Get the length of the file
337 mFileLen = mFile.Seek(0, wxFromEnd);
338 if (mFileLen == wxInvalidOffset || mFile.Error())
339 {
340 mFile.Close();
341 return false;
342 }
343
344 if (mFile.Seek(0, wxFromStart) == wxInvalidOffset || mFile.Error())
345 {
346 mFile.Close();
347 return false;
348 }
349
350 // Check for ID3 tags
351 CheckTags();
352
353 // Scan for the first MP3 frame
354 if (!CheckMP3())
355 {
356 mFile.Close();
357 return false;
358 }
359
360 return true;
361}
362
364{
365 // We do this twice to allow them to be in any order
366 for (int i = 0; i < 2; ++i)
367 {
368 CheckAPETags(false);
369 CheckID3V2Tags(false);
370 }
371
372 // We do this twice to allow them to be in any order. Even though ID3v1 is
373 // supposed to at the end, some apps put the v2 tags after the v1 tags.
374 for (int i = 0; i < 2; ++i)
375 {
376 CheckAPETags(true);
378 CheckLyrics();
379 CheckID3V2Tags(true);
380 }
381
382 return;
383}
384
386{
387 int offset = atEnd ? mFileLen - 32 : mFilePos;
388
389 // Ensure file is positioned to start of (possible) tags
390 if (mFile.Seek(offset, wxFromStart) == wxInvalidOffset || mFile.Error())
391 {
392 return;
393 }
394
395 // An APE tag header is 32 bytes
396 if (mFile.Read(mInputBuffer, 32) != 32 || mFile.Error())
397 {
398 return;
399 }
400
401 // Do we have an APE preamble?
402 if (memcmp(mInputBuffer, "APETAGEX", 8) != 0)
403 {
404 return;
405 }
406
407 // Get the (little endian) length
408 wxFileOffset len = (mInputBuffer[12] & 0xff) |
409 ((mInputBuffer[13] & 0xff) << 8) |
410 ((mInputBuffer[14] & 0xff) << 16) |
411 ((mInputBuffer[15] & 0xff) << 24);
412
413 // Get needed flags
414 bool hasHeader = mInputBuffer[23] & 0x80;
415
416 // Skip the tags
417 if (!atEnd)
418 {
419 mFilePos += (32 + len);
420 }
421 else
422 {
423 mFileLen -= ((hasHeader ? 32 : 0) + len);
424 }
425}
426
428{
429 // Ensure file is positioned to start of (possible) tags
430 if (mFile.Seek(mFileLen - 128, wxFromStart) == wxInvalidOffset || mFile.Error())
431 {
432 return;
433 }
434
435 // An ID3v1 tag header is 3 bytes
436 if (mFile.Read(mInputBuffer, 3) != 3 || mFile.Error())
437 {
438 return;
439 }
440
441 // Do we have ID3v1 tags?
442 if (memcmp(mInputBuffer, "TAG", 3) != 0)
443 {
444 return;
445 }
446
447 // Adjust file length
448 mFileLen -= 128;
449
450 // Remember that we have tags
451 mHaveID3 = true;
452}
453
455{
456 int offset = mFileLen - 9;
457
458 // Ensure file is positioned to start of (possible) lyrics
459 if (mFile.Seek(offset, wxFromStart) == wxInvalidOffset || mFile.Error())
460 {
461 return;
462 }
463
464 // An Lyrics3 footeris 9 bytes
465 if (mFile.Read(mInputBuffer, 9) != 9 || mFile.Error())
466 {
467 return;
468 }
469
470 // Found a v1 Lyrics footer?
471 if (memcmp(mInputBuffer, "LYRICSEND", 9) == 0)
472 {
473 wxFileOffset pos = wxMax(offset - 5100, 0);
474 size_t len = offset - pos;
475
476 // Ensure file is positioned to start of (possible) lyrics
477 if (mFile.Seek(pos, wxFromStart) == wxInvalidOffset || mFile.Error())
478 {
479 return;
480 }
481
482 // Read the lyrics
483 if (mFile.Read(mInputBuffer, len) != len || mFile.Error())
484 {
485 return;
486 }
487
488 // Search forward to find the beginning of the lyrics
489 for (size_t i = 0; i < len; ++i)
490 {
491 if (memcmp(&mInputBuffer[i], "LYRICSBEGIN", 11) == 0)
492 {
493 // Adjust the file length to exclude the lyrics
494 mFileLen = pos + i;
495 break;
496 }
497 }
498 }
499 // Found a v2 Lyrics footer?
500 else if (memcmp(mInputBuffer, "LYRICS200", 9) == 0)
501 {
502 // Ensure file is positioned to start of (possible) lyrics
503 if (mFile.Seek(-15, wxFromCurrent) == wxInvalidOffset || mFile.Error())
504 {
505 return;
506 }
507
508 // An Lyrics3v2 length is 6 bytes
509 if (mFile.Read(mInputBuffer, 6) != 6 || mFile.Error())
510 {
511 return;
512 }
513
514 // Adjust the file length to exclude the lyrics
515 mInputBuffer[6] = 0;
516 mFileLen -= (wxAtoi((char *) mInputBuffer) + 15);
517 }
518}
519
521{
522 int offset = atEnd ? mFileLen - 10 : mFilePos;
523
524 // Ensure file is positioned to start of (possible) tags
525 if (mFile.Seek(offset, wxFromStart) == wxInvalidOffset || mFile.Error())
526 {
527 return;
528 }
529
530 // An ID3v2 tag header is 10 bytes
531 if (mFile.Read(mInputBuffer, 10) != 10 || mFile.Error())
532 {
533 return;
534 }
535
536 // Do we have an ID3v2 header or footer?
537 if (memcmp(mInputBuffer, atEnd ? "3DI" : "ID3", 3) != 0)
538 {
539 return;
540 }
541
542 // Get and decode the length
543 wxFileOffset len = (mInputBuffer[6] & 0x7f);
544 len = (len << 7) | (mInputBuffer[7] & 0x7f);
545 len = (len << 7) | (mInputBuffer[8] & 0x7f);
546 len = (len << 7) | (mInputBuffer[9] & 0x7f);
547
548 // Skip the tags
549 if (!atEnd)
550 {
551 mFilePos += (10 + len);
552 }
553 else
554 {
555 mFileLen -= (10 + len + 10);
556 }
557
558 // Remember that we have tags
559 mHaveID3 = true;
560}
561
563{
564 wxFileOffset savedPos = mFilePos;
565
566 // Ensure file is positioned to start of 1st mp3 frame
567 if (mFile.Seek(mFilePos, wxFromStart) == wxInvalidOffset || mFile.Error())
568 {
569 return false;
570 }
571
572 // Load as much as will fit into the buffer
573 if (!FillBuffer())
574 {
575 return false;
576 }
577
578 // Initialize mad stream
579 mad_stream stream;
580 mad_stream_init(&stream);
581 mad_stream_buffer(&stream, mInputBuffer, mInputBufferLen);
582
583 // And header
584 mad_header header;
585 mad_header_init(&header);
586
587 // Scan the input buffer for 2 consecutive MP3 frames. When the header
588 // decoder finds a frame, it decodes it and ensures it is followed by
589 // another frame or EOF...thus 2 (or 1) consecutive frame(s) are detected.
590 int consecutive = 1;
591 while (consecutive > 0)
592 {
593 // Decode the header at the current stream position.
594 if (mad_header_decode(&header, &stream))
595 {
596 // End of buffer.
597 if (stream.error != MAD_ERROR_NONE)
598 {
599 break;
600 }
601 }
602
603 consecutive -= 1;
604 }
605
606 // Remember how many bytes were processed
607 int used = stream.this_frame - stream.buffer;
608
609 // Cleanup
610 mad_header_finish(&header);
611 mad_stream_finish(&stream);
612
613 // Did we find all that we wanted?
614 if (consecutive)
615 {
616 return false;
617 }
618
619 // Reset file controls
620 mInputBufferLen = 0;
621
622 // Reposition file to start of mp3 frames to prepare for the Import.
623 mFilePos = savedPos + used;
624 if (mFile.Seek(mFilePos, wxFromStart) == wxInvalidOffset || mFile.Error())
625 {
626 return false;
627 }
628
629 // Looks like an MP3...
630 return true;
631}
632
634{
635 // We either want enough to fill the input buffer or what's left in the file
636 auto want = wxMin(INPUT_BUFFER_SIZE - mInputBufferLen, mFileLen - mFilePos);
637 if (want > 0)
638 {
639 // We should always get what we ask for
640 auto got = mFile.Read(&mInputBuffer[mInputBufferLen], want);
641 if (got != want || mFile.Error())
642 {
643 return false;
644 }
645
646 // Adjust input control
647 mInputBufferLen += got;
648 mFilePos += got;
649 }
650
651 // MAD requires that we add MAD_BUFFER_GUARD extra bytes when we've processed
652 // all of the MP3 frames. Otherwise, we will drop the last frame.
653 if (mFilePos == mFileLen)
654 {
655 memset(&mInputBuffer[mInputBufferLen], 0, MAD_BUFFER_GUARD);
656 mInputBufferLen += MAD_BUFFER_GUARD;
657 }
658
659 return true;
660}
661
663{
664#ifdef USE_LIBID3TAG
665 struct id3_file *id3file = NULL;
666 auto cleanup = finally([&]
667 {
668 if (id3file)
669 {
670 id3_file_close(id3file);
671 }
672 });
673
674 // Use id3_file_fdopen() instead of id3_file_open since wxWidgets can open a
675 // file with a Unicode name and id3_file_open() can't (under Windows).
676 id3file = id3_file_fdopen(mFile.fd(), ID3_FILE_MODE_READONLY);
677 if (!id3file)
678 {
679 return;
680 }
681
682 // The file descriptor is now owned by "id3file", so we must tell "mFile" to forget
683 // about it.
684 mFile.Detach();
685
686 // Load the tags
687 struct id3_tag *id3tags = id3_file_tag(id3file);
688 if (!id3tags || id3tags->nframes == 0)
689 {
690 return;
691 }
692
693 // Convert from libid3tag's ucs4 type to wxString.
694 //
695 // The ucs4 type is unsigned long which can be 8 bytes instead
696 // of the expected 4 bytes for a UTF-32 character, so we have
697 // to convert to unsigned int and then to wxString.
698 wxMBConvUTF32 converter;
699 auto toString = [=](const id3_ucs4_t *in)
700 {
701 // Count the number of characters
702 size_t len = 0;
703 for (const id3_ucs4_t *p = in; *p; p++)
704 {
705 len++;
706 }
707
708 // Would like to use std::dynarray or runtime-sized array,
709 // but VS doesn't support either.
710 wxUint32 *buf = (wxUint32 *) alloca((len + 1) * sizeof(wxUint32));
711
712 // Copy and convert to unsigned int
713 wxUint32 *out;
714 for (out = buf; *in; in++, out++)
715 {
716 *out = (wxUint32) (*in);
717 }
718 *out = 0;
719
720 // Finally convert to and return wxString
721 return wxString((char *) buf, converter);
722 };
723
724 tags->Clear();
725
726 // Extract tags from ID3 frames and add to our tags
727 bool have_year = false;
728 for (unsigned int i = 0; i < id3tags->nframes; ++i)
729 {
730 struct id3_frame *frame = id3tags->frames[i];
731
732#if 0
733 wxLogDebug("ID: %08x '%4s'", (int) *(int *)frame->id, frame->id);
734 wxLogDebug("Desc: %s", frame->description);
735 wxLogDebug("Num fields: %d", frame->nfields);
736
737 for (unsigned int j = 0; j < frame->nfields; ++j)
738 {
739 wxLogDebug("field %d type %d", j, frame->fields[j].type);
740 if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST)
741 {
742 wxLogDebug("num strings %d", frame->fields[j].stringlist.nstrings);
743 }
744 }
745#endif
746
747 wxString n;
748 wxString v;
749
750 // Determine the tag name
751 if (strcmp(frame->id, ID3_FRAME_TITLE) == 0)
752 {
753 n = TAG_TITLE;
754 }
755 else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0)
756 {
757 n = TAG_ARTIST;
758 }
759 else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0)
760 {
761 n = TAG_ALBUM;
762 }
763 else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0)
764 {
765 n = TAG_TRACK;
766 }
767 else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0)
768 {
769 // LLL: When libid3tag encounters the "TYER" tag, it converts it to a
770 // "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
771 // list of tags using the first 4 characters of the "TYER" tag.
772 // Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
773 // will always be encountered first in the list. We want to use
774 // it since the converted "TYER" tag may have been truncated.
775 if (have_year)
776 {
777 continue;
778 }
779 n = TAG_YEAR;
780 have_year = true;
781 }
782 else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0)
783 {
784 n = TAG_COMMENTS;
785 }
786 else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0)
787 {
788 n = TAG_GENRE;
789 }
790 else
791 {
792 // Use frame description as default tag name. The descriptions
793 // may include several "meanings" separated by "/" characters, so
794 // we just use the first meaning
795 n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
796 }
797
798 // Now get the tag value
799 const id3_ucs4_t *ustr = NULL;
800
801 if (n == TAG_COMMENTS)
802 {
803 ustr = id3_field_getfullstring(&frame->fields[3]);
804 }
805 else if (frame->nfields == 3)
806 {
807 ustr = id3_field_getstring(&frame->fields[1]);
808 if (ustr)
809 {
810 n = toString(ustr);
811 }
812
813 ustr = id3_field_getstring(&frame->fields[2]);
814 }
815 else if (frame->nfields >= 2)
816 {
817 ustr = id3_field_getstrings(&frame->fields[1], 0);
818 }
819
820 // Convert the value
821 if (ustr)
822 {
823 v = toString(ustr);
824 }
825
826 // And add it to the list of tags
827 if (!n.empty() && !v.empty())
828 {
829 tags->SetTag(n, v);
830 }
831 }
832
833 // Convert v1 genre to name
834 if (tags->HasTag(TAG_GENRE))
835 {
836 long g = -1;
837 if (tags->GetTag(TAG_GENRE).ToLong(&g))
838 {
839 tags->SetTag(TAG_GENRE, tags->GetGenre(g));
840 }
841 }
842#else
843 (void) tags;
844#endif
845}
846
847//
848// MAD Callbacks
849//
850
851// The input callback is called when the decoder wants more data
853 struct mad_stream *stream)
854{
855 auto cb = [&]()
856 {
857 return ((MP3ImportFileHandle *) that)->InputCB(stream);
858 };
859
860 return GuardedCall<mad_flow>(cb, MakeSimpleGuard(MAD_FLOW_BREAK));
861}
862
864{
865 // Update the progress
866 mUpdateResult = mProgress->Update((wxLongLong_t) mFilePos, (wxLongLong_t) mFileLen);
868 {
869 return MAD_FLOW_STOP;
870 }
871
872 // Stop if we've consumed all of the MP3 data
873 if (mFilePos == mFileLen)
874 {
875 return MAD_FLOW_STOP;
876 }
877
878 // "Each time you refill your buffer, you need to preserve the data in
879 // your existing buffer from stream.next_frame to the end.
880 //
881 // This usually amounts to calling memmove() on this unconsumed portion
882 // of the buffer and appending NEW data after it, before calling
883 // mad_stream_buffer()
884 // -- Rob Leslie, on the mad-dev mailing list
885 if (stream->next_frame)
886 {
887 mInputBufferLen -= (stream->next_frame - mInputBuffer);
888 memmove(mInputBuffer, stream->next_frame, mInputBufferLen);
889 }
890
891 // Refill the buffer
892 if (!FillBuffer())
893 {
894 return MAD_FLOW_BREAK;
895 }
896
897 // And give it back to MAD
898 mad_stream_buffer(stream, mInputBuffer, mInputBufferLen);
899
900 return MAD_FLOW_CONTINUE;
901}
902
903// The filter callback lets us examine each frame and decide if it should be
904// kept or tossed. We use this to detect the Xing or LAME tags.
906 struct mad_stream const *stream,
907 struct mad_frame *frame)
908{
909 auto cb = [&]()
910 {
911 return ((MP3ImportFileHandle *) that)->FilterCB(stream, frame);
912 };
913
914 return GuardedCall<mad_flow>(cb, MakeSimpleGuard(MAD_FLOW_BREAK));
915}
916
917mad_flow MP3ImportFileHandle::FilterCB(struct mad_stream const *stream,
918 struct mad_frame *frame)
919{
920 // We only want to jinspect the first frame, so disable future calls
921 mDecoder.filter_func = nullptr;
922
923 // Is it a VBRI info frame?
924 if (memcmp(&stream->this_frame[4 + 32], "VBRI", 4) == 0)
925 {
926 mDelay = (stream->this_frame[4 + 32 + 6] & 0xff) << 8 |
927 (stream->this_frame[4 + 32 + 7] & 0xff);
928
929 return MAD_FLOW_CONTINUE;
930 }
931
932 // Look for Xing/Info information
933
934 // Get the ancillary data ptr and length. If the frame has CRC protection, we make
935 // a small adjustment to get around an apparent bug in libmad.
936 auto ptr = stream->anc_ptr.byte - (frame->header.flags & MAD_FLAG_PROTECTION ? 2 : 0);
937 int len = stream->anc_bitlen / 8;
938
939 // Ensure it's something we can understand
940 if (len < 4 || (memcmp(ptr, "Xing", 4) != 0 && memcmp(ptr, "Info", 4) != 0))
941 {
942 return MAD_FLOW_CONTINUE;
943 }
944
945 // Skip the tag
946 ptr += 4;
947 len -= 4;
948
949 enum flagBits
950 {
951 hasFrames = 0x0001,
952 hasBytes = 0x0002,
953 hasToc = 0x0004,
954 hasScale = 0x0008
955 };
956
957 // Extract the flags
958 unsigned int flags = (((((ptr[0] << 8) + ptr[1]) << 8) + ptr[2]) << 8) + ptr[3];
959 ptr += 4;
960 len -= 4;
961
962 // Skip the number of frames
963 if (len >= 4 && flags & hasFrames)
964 {
965 ptr += 4;
966 len -= 4;
967 }
968
969 // Skip the number of bytes
970 if (len >= 4 && flags & hasBytes)
971 {
972 ptr += 4;
973 len -= 4;
974 }
975
976 // Skip the TOC
977 if (len >= 100 && flags & hasToc)
978 {
979 ptr += 100;
980 len -= 100;
981 }
982
983 // Skip the VBR Scale
984 if (len >= 4 && flags & hasScale)
985 {
986 ptr += 4;
987 len -= 4;
988 }
989
990 // Bail if LAME wasn't the encoder or we don't have enough ancillary data left
991 if (len < 24 || memcmp(ptr, "LAME", 4) != 0)
992 {
993 return MAD_FLOW_IGNORE;
994 }
995
996 // Skip down to the delay and padding
997 ptr += 21;
998 len -= 21;
999
1000 // Extract the delay and padding and adjust for decoder delay
1001 mDelay = (ptr[0] << 4) + (ptr[1] >> 4) + MAD_DELAY;
1002 mPadding = ((ptr[1] & 0x0f) << 8) + ptr[2] - MAD_DELAY;
1003 if (mPadding < 0)
1004 {
1005 mPadding = 0;
1006 }
1007
1008 return MAD_FLOW_IGNORE;
1009}
1010
1011// The output callback is called every time the decoder has finished decoding
1012 // a frame, allowing us to use the decoded data
1014 struct mad_header const *header,
1015 struct mad_pcm *pcm)
1016{
1017 auto cb = [&]()
1018 {
1019 return ((MP3ImportFileHandle *) that)->OutputCB(header, pcm);
1020 };
1021
1022 return GuardedCall<mad_flow>(cb, MakeSimpleGuard(MAD_FLOW_BREAK));
1023}
1024
1025enum mad_flow MP3ImportFileHandle::OutputCB(struct mad_header const * WXUNUSED(header),
1026 struct mad_pcm *pcm)
1027{
1028 // If this is the first run, we need to create the WaveTracks that
1029 // will hold the data. We do this now because now is the first
1030 // moment when we know how many channels there are.
1031 if (mChannels.empty())
1032 {
1033 mNumChannels = pcm->channels;
1034
1035 mChannels.resize(mNumChannels);
1036
1037 for (auto &channel: mChannels)
1038 {
1039 // Mad library header explains the 32 bit fixed point format with
1040 // 28 fractional bits. Effective sample format must therefore be
1041 // more than 24, and this is our only choice now.
1042 channel = NewWaveTrack(*mTrackFactory, floatSample, pcm->samplerate);
1043 }
1044 }
1045
1046 // Get the number of samples in each channel
1047 auto samples = pcm->length;
1048
1049 // Convert libmad samples to float and append to WaveTracks
1050 for (int chn = 0; chn < mNumChannels; ++chn)
1051 {
1052 // Number of samples will never be more than 1152
1053 float sampleBuf[1152];
1054 wxASSERT(samples <= 1152);
1055
1056 // Copy over the samples
1057 for (int sample = 0; sample < samples; ++sample)
1058 {
1059 // Convert libmad's fixed point representation to float
1060 sampleBuf[sample] = ((float) pcm->samples[chn][sample] / (1L << MAD_F_FRACBITS));
1061 }
1062
1063 // And append to the channel
1064 mChannels[chn]->Append((samplePtr) sampleBuf, floatSample, samples);
1065 }
1066
1067 return MAD_FLOW_CONTINUE;
1068}
1069
1070// The error callback is used when MAD encounters an error and needs to know
1071// how it should proceed
1073 struct mad_stream *stream,
1074 struct mad_frame *frame)
1075{
1076 auto cb = [&]()
1077 {
1078 return ((MP3ImportFileHandle *) that)->ErrorCB(stream, frame);
1079 };
1080
1081 return GuardedCall<mad_flow>(cb, MakeSimpleGuard(MAD_FLOW_BREAK));
1082}
1083
1084enum mad_flow MP3ImportFileHandle::ErrorCB(struct mad_stream *stream,
1085 struct mad_frame *frame)
1086{
1087 // You always get a LOSTSYNC error at EOF, so just ignore it
1088 if (stream->error == MAD_ERROR_LOSTSYNC && mFilePos == mFileLen)
1089 {
1090 return MAD_FLOW_CONTINUE;
1091 }
1092
1093 // This can happen when parsing the first frame. We can use the number of channels
1094 // to test for this since it hasn't been determined yet.
1095 if (stream->error == MAD_ERROR_BADDATAPTR && mNumChannels == 0)
1096 {
1097 return MAD_FLOW_CONTINUE;
1098 }
1099
1100 // Let the user know about the error
1101 using namespace BasicUI;
1102 ShowErrorDialog( {},
1104 XO("Import failed\n\nThis is likely caused by a malformed MP3.\n\n"),
1105 "Opening_malformed_MP3_files");
1106 return MAD_FLOW_BREAK;
1107}
1108
1109#endif
SimpleGuard< R > MakeSimpleGuard(R value) noexcept(noexcept(SimpleGuard< R >{ value }))
Convert a value to a handler function returning that value, suitable for GuardedCall<R>
Toolkit-neutral facade for basic user interface services.
wxArrayStringEx FileExtensions
Definition: Identifier.h:225
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
Definition: Import.cpp:62
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
Definition: Import.h:39
static const auto exts
Definition: ImportMP3.cpp:40
#define DESC
Definition: ImportMP3.cpp:38
static Importer::RegisteredImportPlugin registered
Definition: ImportMP3.cpp:211
#define INPUT_BUFFER_SIZE
Definition: ImportMP3.cpp:86
#define MAD_DELAY
Definition: ImportMP3.cpp:90
The interface that all file import "plugins" (if you want to call them that) must implement....
#define UTF8CTOWX(X)
Definition: Internat.h:159
#define XO(s)
Definition: Internat.h:31
wxString FilePath
Definition: Project.h:20
@ floatSample
Definition: SampleFormat.h:34
char * samplePtr
Definition: SampleFormat.h:49
#define TAG_TRACK
Definition: Tags.h:61
#define TAG_COMMENTS
Definition: Tags.h:64
#define TAG_GENRE
Definition: Tags.h:63
#define TAG_ALBUM
Definition: Tags.h:60
#define TAG_YEAR
Definition: Tags.h:62
#define TAG_TITLE
Definition: Tags.h:58
#define TAG_ARTIST
Definition: Tags.h:59
std::vector< TranslatableString > TranslatableStrings
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
An ImportFileHandle for data.
Definition: ImportPlugin.h:107
FilePath mFilename
Definition: ImportPlugin.h:158
unsigned long long ByteCount
Definition: ImportPlugin.h:127
std::unique_ptr< ProgressDialog > mProgress
Definition: ImportPlugin.h:159
std::shared_ptr< WaveTrack > NewWaveTrack(WaveTrackFactory &trackFactory, sampleFormat effectiveFormat, double rate)
Build a wave track with appropriate format, which will not be narrower than the specified one.
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Definition: ImportPlugin.h:67
An ImportFileHandle for MP3 data.
Definition: ImportMP3.cpp:106
ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
Definition: ImportMP3.cpp:255
void LoadID3(Tags *tags)
Definition: ImportMP3.cpp:662
ByteCount GetFileUncompressedBytes() override
Definition: ImportMP3.cpp:234
MP3ImportFileHandle(const FilePath &filename)
Definition: ImportMP3.cpp:220
const TranslatableStrings & GetStreamInfo() override
Definition: ImportMP3.cpp:245
wxFileOffset mFilePos
Definition: ImportMP3.cpp:154
void SetStreamUsage(wxInt32 StreamID, bool Use) override
Definition: ImportMP3.cpp:251
mad_decoder mDecoder
Definition: ImportMP3.cpp:151
static mad_flow output_cb(void *that, struct mad_header const *header, struct mad_pcm *pcm)
Definition: ImportMP3.cpp:1013
mad_flow ErrorCB(struct mad_stream *stream, struct mad_frame *frame)
Definition: ImportMP3.cpp:1084
mad_flow InputCB(struct mad_stream *stream)
Definition: ImportMP3.cpp:863
void CheckID3V2Tags(bool atEnd)
Definition: ImportMP3.cpp:520
mad_flow FilterCB(struct mad_stream const *stream, struct mad_frame *frame)
Definition: ImportMP3.cpp:917
static mad_flow filter_cb(void *that, struct mad_stream const *stream, struct mad_frame *frame)
Definition: ImportMP3.cpp:905
static mad_flow error_cb(void *that, struct mad_stream *stream, struct mad_frame *frame)
Definition: ImportMP3.cpp:1072
TranslatableString GetFileDescription() override
Definition: ImportMP3.cpp:229
static mad_flow input_cb(void *that, struct mad_stream *stream)
Definition: ImportMP3.cpp:852
wxInt32 GetStreamCount() override
Definition: ImportMP3.cpp:240
mad_flow OutputCB(struct mad_header const *header, struct mad_pcm *pcm)
Definition: ImportMP3.cpp:1025
wxFileOffset mFileLen
Definition: ImportMP3.cpp:155
void CheckAPETags(bool atEnd)
Definition: ImportMP3.cpp:385
unsigned char mInputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD]
Definition: ImportMP3.cpp:157
ProgressResult mUpdateResult
Definition: ImportMP3.cpp:164
NewChannelGroup mChannels
Definition: ImportMP3.cpp:161
WaveTrackFactory * mTrackFactory
Definition: ImportMP3.cpp:160
An ImportPlugin for MP3 data.
Definition: ImportMP3.cpp:93
TranslatableString GetPluginFormatDescription() override
Definition: ImportMP3.cpp:192
wxString GetPluginStringID() override
Definition: ImportMP3.cpp:187
std::unique_ptr< ImportFileHandle > Open(const FilePath &Filename, AudacityProject *) override
Definition: ImportMP3.cpp:197
ID3 Tags (for MP3)
Definition: Tags.h:73
void Clear()
Definition: Tags.cpp:308
bool HasTag(const wxString &name) const
Definition: Tags.cpp:407
wxString GetGenre(int value)
Definition: Tags.cpp:383
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:441
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:416
Holds a msgid for the translation catalog; may also bind format arguments.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:612
struct in the MPEG library, used for MP3 compression by MP3Exporter
struct in the MPEG library, used for MP3 compression by MP3Exporter
struct in the MPEG library, used for MP3 compression by MP3Exporter
struct in the MPEG library, used for MP3 compression by MP3Exporter
struct in the MPEG library, used for MP3 compression by MP3Exporter
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
TranslatableString DefaultCaption()
"Message", suitably translated
Definition: BasicUI.cpp:70
ProgressResult
Definition: BasicUI.h:145
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:241
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150