Audacity  2.2.2
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 #include "../Audacity.h"
30 #include "ImportMP3.h"
31 
32 // For compilers that support precompilation, includes "wx/wx.h".
33 #include <wx/wxprec.h>
34 
35 #ifndef WX_PRECOMP
36 #include <wx/window.h>
37 #endif
38 
39 #include <wx/defs.h>
40 #include <wx/intl.h>
41 
42 #include "../AudacityException.h"
43 #include "../Prefs.h"
44 #include "Import.h"
45 #include "ImportPlugin.h"
46 #include "../Internat.h"
47 #include "../Tags.h"
48 
49 #define DESC _("MP3 files")
50 
51 static const wxChar *exts[] =
52 {
53  wxT("mp3"),
54  wxT("mp2"),
55  wxT("mpa")
56 };
57 
58 #ifndef USE_LIBMAD
59 
60 void GetMP3ImportPlugin(ImportPluginList &importPluginList,
61  UnusableImportPluginList &unusableImportPluginList)
62 {
63  unusableImportPluginList.push_back(
64  make_movable<UnusableImportPlugin>
65  (DESC, wxArrayString(WXSIZEOF(exts), exts))
66  );
67 }
68 
69 #else /* USE_LIBMAD */
70 
71 #include <wx/textctrl.h>
72 #include <wx/file.h>
73 #include <wx/thread.h>
74 #include <wx/progdlg.h>
75 #include <wx/string.h>
76 #include <wx/timer.h>
77 #include <wx/intl.h>
78 
79 extern "C" {
80 #include "mad.h"
81 
82 #ifdef USE_LIBID3TAG
83 #include <id3tag.h>
84 #endif
85 }
86 
87 #include "../WaveTrack.h"
88 
89 #define INPUT_BUFFER_SIZE 65535u
90 #define PROGRESS_SCALING_FACTOR 100000
91 
92 /* this is a private structure we can use for whatever we like, and it will get
93  * passed to each of the callback routines, allowing us to keep track of
94  * things. */
95 struct private_data {
96  wxFile *file; /* the file containing the mp3 data we're feeding the encoder */
97  ArrayOf<unsigned char> inputBuffer{ INPUT_BUFFER_SIZE };
98  int inputBufferFill; /* amount of data in inputBuffer */
99  TrackFactory *trackFactory;
100  TrackHolders channels;
101  ProgressDialog *progress;
102  unsigned numChannels;
103  ProgressResult updateResult;
104  bool id3checked;
105  bool eof; /* having supplied both underlying file and guard pad data */
106 };
107 
108 class MP3ImportPlugin final : public ImportPlugin
109 {
110 public:
111  MP3ImportPlugin():
112  ImportPlugin(wxArrayString(WXSIZEOF(exts), exts))
113  {
114  }
115 
116  ~MP3ImportPlugin() { }
117 
118  wxString GetPluginStringID() { return wxT("libmad"); }
119  wxString GetPluginFormatDescription();
120  std::unique_ptr<ImportFileHandle> Open(const wxString &Filename) override;
121 };
122 
123 class MP3ImportFileHandle final : public ImportFileHandle
124 {
125 public:
126  MP3ImportFileHandle(std::unique_ptr<wxFile> &&file, wxString filename):
127  ImportFileHandle(filename),
128  mFile(std::move(file))
129  {
130  }
131 
133 
134  wxString GetFileDescription() override;
135  ByteCount GetFileUncompressedBytes() override;
136  ProgressResult Import(TrackFactory *trackFactory, TrackHolders &outTracks,
137  Tags *tags) override;
138 
139  wxInt32 GetStreamCount() override { return 1; }
140 
141  const wxArrayString &GetStreamInfo() override
142  {
143  static wxArrayString empty;
144  return empty;
145  }
146 
147  void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
148  {}
149 
150 private:
151  void ImportID3(Tags *tags);
152 
153  std::unique_ptr<wxFile> mFile;
154  void *mUserData;
155  mad_decoder mDecoder;
156 };
157 
158 void GetMP3ImportPlugin(ImportPluginList &importPluginList,
159  UnusableImportPluginList & WXUNUSED(unusableImportPluginList))
160 {
161  importPluginList.push_back( make_movable<MP3ImportPlugin>() );
162 }
163 
164 /* The MAD callbacks */
165 enum mad_flow input_cb(void *_data, struct mad_stream *stream);
166 enum mad_flow output_cb(void *_data,
167  struct mad_header const *header,
168  struct mad_pcm *pcm);
169 enum mad_flow error_cb(void *_data, struct mad_stream *stream,
170  struct mad_frame *frame);
171 
172 /* convert libmad's fixed point representation to 16 bit signed integers. This
173  * code is taken verbatim from minimad.c. */
174 
175 inline float scale(mad_fixed_t sample)
176 {
177  return (float) (sample / (float) (1L << MAD_F_FRACBITS));
178 }
179 
180 
181 wxString MP3ImportPlugin::GetPluginFormatDescription()
182 {
183  return DESC;
184 }
185 
186 std::unique_ptr<ImportFileHandle> MP3ImportPlugin::Open(const wxString &Filename)
187 {
188  auto file = std::make_unique<wxFile>(Filename);
189 
190  if (!file->IsOpened())
191  return nullptr;
192 
193  /* There's no way to tell if this is a valid mp3 file before actually
194  * decoding, so we return a valid FileHandle. */
195 
196  return std::make_unique<MP3ImportFileHandle>(std::move(file), Filename);
197 }
198 
199 wxString MP3ImportFileHandle::GetFileDescription()
200 {
201  return DESC;
202 }
203 
204 auto MP3ImportFileHandle::GetFileUncompressedBytes() -> ByteCount
205 {
206  // TODO
207  return 0;
208 }
209 
210 ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHolders &outTracks,
211  Tags *tags)
212 {
213  outTracks.clear();
214 
215  CreateProgress();
216 
217  /* Prepare decoder data, initialize decoder */
218 
219  private_data privateData;
220  privateData.file = mFile.get();
221  privateData.inputBufferFill = 0;
222  privateData.progress = mProgress.get();
223  privateData.updateResult= ProgressResult::Success;
224  privateData.id3checked = false;
225  privateData.numChannels = 0;
226  privateData.trackFactory= trackFactory;
227  privateData.eof = false;
228 
229  mad_decoder_init(&mDecoder, &privateData, input_cb, 0, 0, output_cb, error_cb, 0);
230 
231  /* and send the decoder on its way! */
232 
233  bool res = (mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0) &&
234  (privateData.numChannels > 0) &&
235  !(privateData.updateResult == ProgressResult::Cancelled) &&
236  !(privateData.updateResult == ProgressResult::Failed);
237 
238  mad_decoder_finish(&mDecoder);
239 
240  if (!res) {
241  /* failure */
242  /* wxPrintf("failure\n"); */
243  return (privateData.updateResult);
244  }
245 
246  /* success */
247  /* wxPrintf("success\n"); */
248 
249  /* copy the WaveTrack pointers into the Track pointer list that
250  * we are expected to fill */
251  for(const auto &channel : privateData.channels) {
252  channel->Flush();
253  }
254  outTracks.swap(privateData.channels);
255 
256  /* Read in any metadata */
257  ImportID3(tags);
258 
259  return privateData.updateResult;
260 }
261 
262 MP3ImportFileHandle::~MP3ImportFileHandle()
263 {
264 }
265 
266 void MP3ImportFileHandle::ImportID3(Tags *tags)
267 {
268 #ifdef USE_LIBID3TAG
269  wxFile f; // will be closed when it goes out of scope
270  struct id3_file *fp = NULL;
271  auto cleanup = finally([&]{
272  if (fp)
273  id3_file_close(fp);
274  });
275 
276  if (f.Open(mFilename)) {
277  // Use id3_file_fdopen() instead of id3_file_open since wxWidgets can open a
278  // file with a Unicode name and id3_file_open() can't (under Windows).
279  fp = id3_file_fdopen(f.fd(), ID3_FILE_MODE_READONLY);
280  }
281 
282  if (!fp) {
283  return;
284  }
285 
286  // The file descriptor is now owned by "fp", so we must tell "f" to forget
287  // about it.
288  f.Detach();
289 
290  struct id3_tag *tp = id3_file_tag(fp);
291  if (!tp)
292  return;
293 
294  tags->Clear();
295 
296  // Loop through all frames
297  bool have_year = false;
298  for (int i = 0; i < (int) tp->nframes; i++) {
299  struct id3_frame *frame = tp->frames[i];
300 
301  // wxPrintf("ID: %08x '%4s'\n", (int) *(int *)frame->id, frame->id);
302  // wxPrintf("Desc: %s\n", frame->description);
303  // wxPrintf("Num fields: %d\n", frame->nfields);
304 
305  // for (int j = 0; j < (int) frame->nfields; j++) {
306  // wxPrintf("field %d type %d\n", j, frame->fields[j].type );
307  // if (frame->fields[j].type == ID3_FIELD_TYPE_STRINGLIST) {
308  // wxPrintf("num strings %d\n", frame->fields[j].stringlist.nstrings);
309  // }
310  // }
311 
312  wxString n, v;
313 
314  // Determine the tag name
315  if (strcmp(frame->id, ID3_FRAME_TITLE) == 0) {
316  n = TAG_TITLE;
317  }
318  else if (strcmp(frame->id, ID3_FRAME_ARTIST) == 0) {
319  n = TAG_ARTIST;
320  }
321  else if (strcmp(frame->id, ID3_FRAME_ALBUM) == 0) {
322  n = TAG_ALBUM;
323  }
324  else if (strcmp(frame->id, ID3_FRAME_TRACK) == 0) {
325  n = TAG_TRACK;
326  }
327  else if (strcmp(frame->id, ID3_FRAME_YEAR) == 0) {
328  // LLL: When libid3tag encounters the "TYER" tag, it converts it to a
329  // "ZOBS" (obsolete) tag and adds a "TDRC" tag at the end of the
330  // list of tags using the first 4 characters of the "TYER" tag.
331  // Since we write both the "TDRC" and "TYER" tags, the "TDRC" tag
332  // will always be encountered first in the list. We want use it
333  // since the converted "TYER" tag may have been truncated.
334  if (have_year) {
335  continue;
336  }
337  n = TAG_YEAR;
338  have_year = true;
339  }
340  else if (strcmp(frame->id, ID3_FRAME_COMMENT) == 0) {
341  n = TAG_COMMENTS;
342  }
343  else if (strcmp(frame->id, ID3_FRAME_GENRE) == 0) {
344  n = TAG_GENRE;
345  }
346  else {
347  // Use frame description as default tag name. The descriptions
348  // may include several "meanings" separated by "/" characters, so
349  // we just use the first meaning
350  n = UTF8CTOWX(frame->description).BeforeFirst(wxT('/'));
351  }
352 
353  const id3_ucs4_t *ustr = NULL;
354 
355  if (n == TAG_COMMENTS) {
356  ustr = id3_field_getfullstring(&frame->fields[3]);
357  }
358  else if (frame->nfields == 3) {
359  ustr = id3_field_getstring(&frame->fields[1]);
360  if (ustr) {
361  // Is this duplication really needed?
362  MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
363  n = UTF8CTOWX(str.get());
364  }
365 
366  ustr = id3_field_getstring(&frame->fields[2]);
367  }
368  else if (frame->nfields >= 2) {
369  ustr = id3_field_getstrings(&frame->fields[1], 0);
370  }
371 
372  if (ustr) {
373  // Is this duplication really needed?
374  MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
375  v = UTF8CTOWX(str.get());
376  }
377 
378  if (!n.IsEmpty() && !v.IsEmpty()) {
379  tags->SetTag(n, v);
380  }
381  }
382 
383  // Convert v1 genre to name
384  if (tags->HasTag(TAG_GENRE)) {
385  long g = -1;
386  if (tags->GetTag(TAG_GENRE).ToLong(&g)) {
387  tags->SetTag(TAG_GENRE, tags->GetGenre(g));
388  }
389  }
390 #endif // ifdef USE_LIBID3TAG
391 }
392 
393 //
394 // MAD Callbacks
395 //
396 
397 /* The input callback is called when the decoder wants more data. */
398 
399 enum mad_flow input_cb(void *_data, struct mad_stream *stream)
400 {
401  struct private_data *data = (struct private_data *)_data;
402 
403  data->updateResult = data->progress->Update((wxULongLong_t)data->file->Tell(),
404  (wxULongLong_t)data->file->Length() != 0 ?
405  (wxULongLong_t)data->file->Length() : 1);
406  if(data->updateResult != ProgressResult::Success)
407  return MAD_FLOW_STOP;
408 
409  if (data->eof) {
410  /* different from data->File->Eof(), this means the underlying
411  file has reached eof *and* we have subsequently supplied the
412  final padding zeros */
413  return MAD_FLOW_STOP;
414  }
415 
416 #ifdef USE_LIBID3TAG
417  if (!data->id3checked) {
418  data->file->Read(data->inputBuffer.get(), ID3_TAG_QUERYSIZE);
419  int len = id3_tag_query(data->inputBuffer.get(), ID3_TAG_QUERYSIZE);
420  if (len > 0) {
421  data->file->Seek(len, wxFromStart);
422  }
423  else {
424  data->file->Seek(0);
425  }
426 
427  data->id3checked = true;
428  }
429 #endif
430 
431  /* "Each time you refill your buffer, you need to preserve the data in
432  * your existing buffer from stream.next_frame to the end.
433  *
434  * This usually amounts to calling memmove() on this unconsumed portion
435  * of the buffer and appending NEW data after it, before calling
436  * mad_stream_buffer()"
437  * -- Rob Leslie, on the mad-dev mailing list */
438 
439  int unconsumedBytes;
440  if(stream->next_frame ) {
441  /* we must use inputBufferFill instead of INPUT_BUFFER_SIZE here
442  because the final buffer of the file may be only partially
443  filled, and we would otherwise be providing too much input
444  after eof */
445  unconsumedBytes = data->inputBuffer.get() + data->inputBufferFill
446  - stream->next_frame;
447  if (unconsumedBytes > 0)
448  memmove(data->inputBuffer.get(), stream->next_frame, unconsumedBytes);
449  }
450  else
451  unconsumedBytes = 0;
452 
453  if (data->file->Eof() &&
454  (unconsumedBytes + MAD_BUFFER_GUARD < INPUT_BUFFER_SIZE)) {
455 
456  /* supply the requisite MAD_BUFFER_GUARD zero bytes to ensure
457  the final frame gets decoded properly, then finish */
458 
459  memset(data->inputBuffer.get() + unconsumedBytes, 0, MAD_BUFFER_GUARD);
460  mad_stream_buffer
461  (stream, data->inputBuffer.get(), MAD_BUFFER_GUARD + unconsumedBytes);
462 
463  data->eof = true; /* so on next call, we will tell mad to stop */
464 
465  return MAD_FLOW_CONTINUE;
466  }
467 
468  off_t read = data->file->Read(data->inputBuffer.get() + unconsumedBytes,
469  INPUT_BUFFER_SIZE - unconsumedBytes);
470 
471  mad_stream_buffer(stream, data->inputBuffer.get(), read + unconsumedBytes);
472 
473  data->inputBufferFill = int(read + unconsumedBytes);
474 
475  return MAD_FLOW_CONTINUE;
476 }
477 
478 /* The output callback is called every time the decoder has finished decoding
479  * a frame, allowing us to use the decoded data */
480 
481 enum mad_flow output_cb(void *_data,
482  struct mad_header const * WXUNUSED(header),
483  struct mad_pcm *pcm)
484 {
485  // Don't C++ exceptions propagate through mad
486  return GuardedCall< mad_flow > ( [&] {
487  int samplerate;
488  struct private_data *data = (struct private_data *)_data;
489 
490  samplerate= pcm->samplerate;
491  auto channels = pcm->channels;
492  const auto samples = pcm->length;
493 
494  /* If this is the first run, we need to create the WaveTracks that
495  * will hold the data. We do this now because now is the first
496  * moment when we know how many channels there are. */
497 
498  if(data->channels.empty()) {
499  data->channels.resize(channels);
500 
501  sampleFormat format = (sampleFormat) gPrefs->
502  Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
503 
504  for(auto &channel: data->channels) {
505  channel = data->trackFactory->NewWaveTrack(format, samplerate);
506  channel->SetChannel(Track::MonoChannel);
507  }
508 
509  /* special case: 2 channels is understood to be stereo */
510  if(channels == 2) {
511  data->channels.begin()->get()->SetChannel(Track::LeftChannel);
512  data->channels.rbegin()->get()->SetChannel(Track::RightChannel);
513  data->channels.begin()->get()->SetLinked(true);
514  }
515  data->numChannels = channels;
516  }
517  else {
518  // This is not the first run, protect us from libmad glitching
519  // on the number of channels
520  channels = data->numChannels;
521  }
522 
523  /* TODO: get rid of this by adding fixed-point support to SampleFormat.
524  * For now, we allocate temporary float buffers to convert the fixed
525  * point samples into something we can feed to the WaveTrack. Allocating
526  * big blocks of data like this isn't a great idea, but it's temporary.
527  */
528  FloatBuffers channelBuffers{ channels, samples };
529  for(size_t smpl = 0; smpl < samples; smpl++)
530  for(int chn = 0; chn < channels; chn++)
531  channelBuffers[chn][smpl] = scale(pcm->samples[chn][smpl]);
532 
533  for(int chn = 0; chn < channels; chn++)
534  data->channels[chn]->Append((samplePtr)channelBuffers[chn].get(),
535  floatSample,
536  samples);
537 
538  return MAD_FLOW_CONTINUE;
539  }, MakeSimpleGuard(MAD_FLOW_BREAK) );
540 }
541 
542 enum mad_flow error_cb(void * WXUNUSED(_data), struct mad_stream * WXUNUSED(stream),
543  struct mad_frame * WXUNUSED(frame))
544 {
545 /* enum mad_flow {
546  MAD_FLOW_CONTINUE = 0x0000,
547  MAD_FLOW_STOP = 0x0010,
548  MAD_FLOW_BREAK = 0x0011,
549  MAD_FLOW_IGNORE = 0x0020
550  }; */
551  /*
552  wxPrintf("decoding error 0x%04x (%s)\n",
553  stream->error, mad_stream_errorstr(stream));
554  */
555 
556  return MAD_FLOW_CONTINUE;
557 
558  /* return MAD_FLOW_BREAK; */
559 }
560 
561 
562 #endif /* defined(USE_LIBMAD) */
void SetTag(const wxString &name, const wxString &value)
Definition: Tags.cpp:449
ProgressResult
#define TAG_TRACK
Definition: Tags.h:65
An ImportFileHandle for data.
Definition: ImportPlugin.h:119
ProgressDialog Class.
struct in the MPEG library, used for MP3 compression by MP3Exporter
#define UTF8CTOWX(X)
Definition: Internat.h:167
#define TAG_TITLE
Definition: Tags.h:62
#define TAG_ARTIST
Definition: Tags.h:63
wxString GetGenre(int value)
Definition: Tags.cpp:391
SimpleGuard< R > MakeSimpleGuard(R value)
struct in the MPEG library, used for MP3 compression by MP3Exporter
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:798
Used to create a WaveTrack, or a LabelTrack.. Implementation of the functions of this class are dispe...
Definition: Track.h:850
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
int format
Definition: ExportPCM.cpp:56
struct in the MPEG library, used for MP3 compression by MP3Exporter
void Clear()
Definition: Tags.cpp:300
The interface that all file import "plugins" (if you want to call them that) must implement...
struct in the MPEG library, used for MP3 compression by MP3Exporter
struct in the MPEG library, used for MP3 compression by MP3Exporter
ID3 Tags (for MP3)
Definition: Tags.h:72
wxString GetTag(const wxString &name) const
Definition: Tags.cpp:424
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Definition: ImportPlugin.h:73
void GetMP3ImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
Definition: ImportMP3.cpp:60
static const wxChar * exts[]
Definition: ImportMP3.cpp:51
An ImportPlugin for MP3 data.
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:469
#define TAG_COMMENTS
Definition: Tags.h:68
#define TAG_GENRE
Definition: Tags.h:67
An UnusableImportPlugin list.
An ImportPlugin list.
#define DESC
Definition: ImportMP3.cpp:49
std::vector< std::unique_ptr< WaveTrack >> TrackHolders
Definition: ImportRaw.h:42
#define TAG_ALBUM
Definition: Tags.h:64
An ImportFileHandle for MP3 data.
#define TAG_YEAR
Definition: Tags.h:66
bool HasTag(const wxString &name) const
Definition: Tags.cpp:415