Audacity  3.0.3
ExportMP3.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ExportMP3.cpp
6 
7  Joshua Haberman
8 
9  This just acts as an interface to LAME. A Lame dynamic library must
10  be present
11 
12  The difficulty in our approach is that we are attempting to use LAME
13  in a way it was not designed to be used. LAME's API is reasonably
14  consistent, so if we were linking directly against it we could expect
15  this code to work with a variety of different LAME versions. However,
16  the data structures change from version to version, and so linking
17  with one version of the header and dynamically linking against a
18  different version of the dynamic library will not work correctly.
19 
20  The solution is to find the lowest common denominator between versions.
21  The bare minimum of functionality we must use is this:
22  1. Initialize the library.
23  2. Set, at minimum, the following global options:
24  i. input sample rate
25  ii. input channels
26  3. Encode the stream
27  4. Call the finishing routine
28 
29  Just so that it's clear that we're NOT free to use whatever features
30  of LAME we like, I'm not including lame.h, but instead enumerating
31  here the extent of functions and structures that we can rely on being
32  able to import and use from a dynamic library.
33 
34  For the record, we aim to support LAME 3.70 on. Since LAME 3.70 was
35  released in April of 2000, that should be plenty.
36 
37 
38  Copyright 2002, 2003 Joshua Haberman.
39  Some portions may be Copyright 2003 Paolo Patruno.
40 
41  This program is free software; you can redistribute it and/or modify
42  it under the terms of the GNU General Public License as published by
43  the Free Software Foundation; either version 2 of the License, or
44  (at your option) any later version.
45 
46  This program is distributed in the hope that it will be useful,
47  but WITHOUT ANY WARRANTY; without even the implied warranty of
48  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49  GNU General Public License for more details.
50 
51  You should have received a copy of the GNU General Public License
52  along with this program; if not, write to the Free Software
53  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 
55 *******************************************************************//********************************************************************/
61 
62 
63 #include "ExportMP3.h"
64 
65 #include <wx/app.h>
66 #include <wx/defs.h>
67 
68 #include <wx/choice.h>
69 #include <wx/checkbox.h>
70 #include <wx/dynlib.h>
71 #include <wx/ffile.h>
72 #include <wx/intl.h>
73 #include <wx/log.h>
74 #include <wx/mimetype.h>
75 #include <wx/radiobut.h>
76 #include <wx/stattext.h>
77 #include <wx/textctrl.h>
78 #include <wx/timer.h>
79 #include <wx/utils.h>
80 #include <wx/window.h>
81 
82 #include "../FileNames.h"
83 #include "../float_cast.h"
84 #include "../Mix.h"
85 #include "../Prefs.h"
86 #include "../ProjectSettings.h"
87 #include "../ProjectWindow.h"
88 #include "../ShuttleGui.h"
89 #include "../Tags.h"
90 #include "../Track.h"
91 #include "../widgets/HelpSystem.h"
92 #include "../widgets/AudacityMessageBox.h"
93 #include "../widgets/ProgressDialog.h"
94 #include "../wxFileNameWrapper.h"
95 
96 #include "Export.h"
97 
98 #include <lame/lame.h>
99 
100 #ifdef USE_LIBID3TAG
101 #include <id3tag.h>
102 #endif
103 
104 //----------------------------------------------------------------------------
105 // ExportMP3Options
106 //----------------------------------------------------------------------------
107 
108 enum MP3ChannelMode : unsigned {
112 };
113 
114 enum : int {
116 
117  //ROUTINE_FAST = 0,
118  //ROUTINE_STANDARD = 1,
119 
124 };
125 
126 /* i18n-hint: kbps is the bitrate of the MP3 file, kilobits per second*/
127 inline TranslatableString n_kbps( int n ){ return XO("%d kbps").Format( n ); }
128 
130  n_kbps(320),
131  n_kbps(256),
132  n_kbps(224),
133  n_kbps(192),
134  n_kbps(160),
135  n_kbps(144),
136  n_kbps(128),
137  n_kbps(112),
138  n_kbps(96),
139  n_kbps(80),
140  n_kbps(64),
141  n_kbps(56),
142  n_kbps(48),
143  n_kbps(40),
144  n_kbps(32),
145  n_kbps(24),
146  n_kbps(16),
147  n_kbps(8),
148 };
149 
150 static const std::vector<int> fixRateValues {
151  320,
152  256,
153  224,
154  192,
155  160,
156  144,
157  128,
158  112,
159  96,
160  80,
161  64,
162  56,
163  48,
164  40,
165  32,
166  24,
167  16,
168  8,
169 };
170 
172  XO("220-260 kbps (Best Quality)"),
173  XO("200-250 kbps"),
174  XO("170-210 kbps"),
175  XO("155-195 kbps"),
176  XO("145-185 kbps"),
177  XO("110-150 kbps"),
178  XO("95-135 kbps"),
179  XO("80-120 kbps"),
180  XO("65-105 kbps"),
181  XO("45-85 kbps (Smaller files)"),
182 };
183 /*
184 static const TranslatableStrings varModeNames {
185  XO("Fast"),
186  XO("Standard"),
187 };
188 */
190  /* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/
191  XO("Insane, 320 kbps"),
192  XO("Extreme, 220-260 kbps"),
193  XO("Standard, 170-210 kbps"),
194  XO("Medium, 145-185 kbps"),
195 };
196 
198  /* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/
199  XO("Insane"),
200  XO("Extreme"),
201  XO("Standard"),
202  XO("Medium"),
203 };
204 
205 static const std::vector< int > sampRates {
206  8000,
207  11025,
208  12000,
209  16000,
210  22050,
211  24000,
212  32000,
213  44100,
214  48000,
215 };
216 
217 #define ID_SET 7000
218 #define ID_VBR 7001
219 #define ID_ABR 7002
220 #define ID_CBR 7003
221 #define ID_QUALITY 7004
222 #define ID_MONO 7005
223 
224 class ExportMP3Options final : public wxPanelWrapper
225 {
226 public:
227 
228  ExportMP3Options(wxWindow *parent, int format);
229  virtual ~ExportMP3Options();
230 
231  void PopulateOrExchange(ShuttleGui & S);
232  bool TransferDataToWindow() override;
233  bool TransferDataFromWindow() override;
234 
235  void OnSET(wxCommandEvent& evt);
236  void OnVBR(wxCommandEvent& evt);
237  void OnABR(wxCommandEvent& evt);
238  void OnCBR(wxCommandEvent& evt);
239  void OnQuality(wxCommandEvent& evt);
240  void OnMono(wxCommandEvent& evt);
241 
242  void LoadNames(const TranslatableStrings &choices);
243 
244 private:
245 
246  wxRadioButton *mStereo;
247  wxRadioButton *mJoint;
248  wxCheckBox *mMono;
249  wxRadioButton *mSET;
250  wxRadioButton *mVBR;
251  wxRadioButton *mABR;
252  wxRadioButton *mCBR;
253  wxChoice *mRate;
254  //wxChoice *mMode;
255 
256  long mSetRate;
257  long mVbrRate;
258  long mAbrRate;
259  long mCbrRate;
260 
261  DECLARE_EVENT_TABLE()
262 };
263 
264 BEGIN_EVENT_TABLE(ExportMP3Options, wxPanelWrapper)
265  EVT_RADIOBUTTON(ID_SET, ExportMP3Options::OnSET)
266  EVT_RADIOBUTTON(ID_VBR, ExportMP3Options::OnVBR)
267  EVT_RADIOBUTTON(ID_ABR, ExportMP3Options::OnABR)
268  EVT_RADIOBUTTON(ID_CBR, ExportMP3Options::OnCBR)
269  EVT_CHOICE(wxID_ANY, ExportMP3Options::OnQuality)
270  EVT_CHECKBOX(ID_MONO, ExportMP3Options::OnMono)
272 
273 ExportMP3Options::ExportMP3Options(wxWindow *parent, int WXUNUSED(format))
276 : wxPanelWrapper(parent, wxID_ANY)
277 {
278  mSetRate = gPrefs->Read(wxT("/FileFormats/MP3SetRate"), PRESET_STANDARD);
279  mVbrRate = gPrefs->Read(wxT("/FileFormats/MP3VbrRate"), QUALITY_2);
280  mAbrRate = gPrefs->Read(wxT("/FileFormats/MP3AbrRate"), 192);
281  mCbrRate = gPrefs->Read(wxT("/FileFormats/MP3CbrRate"), 192);
282 
284  PopulateOrExchange(S);
285 
286  TransferDataToWindow();
287 }
288 
290 {
292 }
293 
295  wxT("/FileFormats/MP3RateModeChoice"),
296  {
297  { wxT("SET"), XXO("Preset") },
298  { wxT("VBR"), XXO("Variable") },
299  { wxT("ABR"), XXO("Average") },
300  { wxT("CBR"), XXO("Constant") },
301  },
302  0, // MODE_SET
303 
304  // for migrating old preferences:
305  {
307  },
308  wxT("/FileFormats/MP3RateMode"),
309 };
310 
312  wxT("/FileFormats/MP3ChannelModeChoice"),
313  {
314  EnumValueSymbol{ wxT("JOINT"), XXO("Joint Stereo") },
315  EnumValueSymbol{ wxT("STEREO"), XXO("Stereo") },
316  },
317  0, // CHANNEL_JOINT
318 
319  // for migrating old preferences:
320  {
322  },
323  wxT("/FileFormats/MP3ChannelMode"),
324 };
325 
329 {
330  bool mono = false;
331  gPrefs->Read(wxT("/FileFormats/MP3ForceMono"), &mono, 0);
332 
333  const TranslatableStrings *choices = nullptr;
334  const std::vector< int > *codes = nullptr;
335  //bool enable;
336  int defrate;
337 
338  S.StartVerticalLay();
339  {
340  S.StartHorizontalLay(wxCENTER);
341  {
342  S.StartMultiColumn(2, wxCENTER);
343  {
344  S.SetStretchyCol(1);
345  S.StartTwoColumn();
346  {
347  S.AddPrompt(XXO("Bit Rate Mode:"));
348 
349  // Bug 2692: Place button group in panel so tabbing will work and,
350  // on the Mac, VoiceOver will announce as radio buttons.
351  S.StartPanel();
352  {
353  S.StartHorizontalLay();
354  {
356  {
357  mSET = S.Id(ID_SET).TieRadioButton();
358  mVBR = S.Id(ID_VBR).TieRadioButton();
359  mABR = S.Id(ID_ABR).TieRadioButton();
360  mCBR = S.Id(ID_CBR).TieRadioButton();
361  }
363  }
364  S.EndHorizontalLay();
365  }
366  S.EndPanel();
367 
368  /* PRL: unfortunately this bit of procedural code must
369  interrupt the mostly-declarative dialog description, until
370  we find a better solution. Because when shuttling values
371  from the dialog, we must shuttle out the MP3RateModeSetting
372  first. */
373 
374  switch( MP3RateModeSetting.ReadEnum() ) {
375  case MODE_SET:
376  choices = &setRateNames;
377  //enable = true;
378  defrate = mSetRate;
379  break;
380 
381  case MODE_VBR:
382  choices = &varRateNames;
383  //enable = true;
384  defrate = mVbrRate;
385  break;
386 
387  case MODE_ABR:
388  choices = &fixRateNames;
389  codes = &fixRateValues;
390  //enable = false;
391  defrate = mAbrRate;
392  break;
393 
394  case MODE_CBR:
395  default:
396  choices = &fixRateNames;
397  codes = &fixRateValues;
398  //enable = false;
399  defrate = mCbrRate;
400  break;
401  }
402 
404  XXO("Quality"),
405  { wxT("/FileFormats/MP3Bitrate"), defrate },
406  *choices,
407  codes
408  );
409  /*
410  mMode = S.Disable(!enable)
411  .TieNumberAsChoice(
412  XXO("Variable Speed:"),
413  { wxT("/FileFormats/MP3VarMode"), ROUTINE_FAST },
414  varModeNames );
415  */
416  S.AddPrompt(XXO("Channel Mode:"));
417  S.StartMultiColumn(2, wxEXPAND);
418  {
419  // Bug 2692: Place button group in panel so tabbing will work and,
420  // on the Mac, VoiceOver will announce as radio buttons.
421  S.StartPanel();
422  {
423  S.StartHorizontalLay();
424  {
426  {
427  mJoint = S.Disable(mono)
428  .TieRadioButton();
429  mStereo = S.Disable(mono)
430  .TieRadioButton();
431  }
433  }
434  S.EndHorizontalLay();
435  }
436  S.EndPanel();
437 
438  mMono = S.Id(ID_MONO).AddCheckBox(XXO("Force export to mono"), mono);
439  }
440  S.EndMultiColumn();
441  }
442  S.EndTwoColumn();
443  }
444  S.EndMultiColumn();
445  }
446  S.EndHorizontalLay();
447  }
448  S.EndVerticalLay();
449 }
450 
454 {
455  return true;
456 }
457 
459 {
460  ShuttleGui S(this, eIsSavingToPrefs);
462 
463  gPrefs->Write(wxT("/FileFormats/MP3SetRate"), mSetRate);
464  gPrefs->Write(wxT("/FileFormats/MP3VbrRate"), mVbrRate);
465  gPrefs->Write(wxT("/FileFormats/MP3AbrRate"), mAbrRate);
466  gPrefs->Write(wxT("/FileFormats/MP3CbrRate"), mCbrRate);
467  gPrefs->Flush();
468 
469  return true;
470 }
471 
472 namespace {
473 
474 int ValidateValue( int nValues, int value, int defaultValue )
475 {
476  return (value >= 0 && value < nValues) ? value : defaultValue;
477 }
478 
479 int ValidateValue( const std::vector<int> &values, int value, int defaultValue )
480 {
481  auto start = values.begin(), finish = values.end(),
482  iter = std::find( start, finish, value );
483  return ( iter != finish ) ? value : defaultValue;
484 }
485 
486 int ValidateIndex( const std::vector<int> &values, int value, int defaultIndex )
487 {
488  auto start = values.begin(), finish = values.end(),
489  iter = std::find( start, finish, value );
490  return ( iter != finish ) ? static_cast<int>( iter - start ) : defaultIndex;
491 }
492 
493 }
494 
497 void ExportMP3Options::OnSET(wxCommandEvent& WXUNUSED(event))
498 {
500 
501  mRate->SetSelection(ValidateValue(setRateNames.size(), mSetRate, 2));
502  mRate->Refresh();
503  //mMode->Enable(true);
504 }
505 
508 void ExportMP3Options::OnVBR(wxCommandEvent& WXUNUSED(event))
509 {
511 
512  mRate->SetSelection(ValidateValue(varRateNames.size(), mVbrRate, 2));
513  mRate->Refresh();
514  //mMode->Enable(true);
515 }
516 
519 void ExportMP3Options::OnABR(wxCommandEvent& WXUNUSED(event))
520 {
522 
523  mRate->SetSelection(ValidateIndex(fixRateValues, mAbrRate, 10));
524  mRate->Refresh();
525  //mMode->Enable(false);
526 }
527 
530 void ExportMP3Options::OnCBR(wxCommandEvent& WXUNUSED(event))
531 {
533 
534  mRate->SetSelection(ValidateIndex(fixRateValues, mCbrRate, 10));
535  mRate->Refresh();
536  //mMode->Enable(false);
537 }
538 
539 void ExportMP3Options::OnQuality(wxCommandEvent& WXUNUSED(event))
540 {
541  int sel = mRate->GetSelection();
542 
543  if (mSET->GetValue()) {
544  mSetRate = sel;
545  }
546  else if (mVBR->GetValue()) {
547  mVbrRate = sel;
548  }
549  else if (mABR->GetValue()) {
550  mAbrRate = fixRateValues[ sel ];
551  }
552  else {
553  mCbrRate = fixRateValues[ sel ];
554  }
555 }
556 
557 void ExportMP3Options::OnMono(wxCommandEvent& /*evt*/)
558 {
559  bool mono = false;
560  mono = mMono->GetValue();
561  mJoint->Enable(!mono);
562  mStereo->Enable(!mono);
563 
564  gPrefs->Write(wxT("/FileFormats/MP3ForceMono"), mono);
565  gPrefs->Flush();
566 }
567 
569 {
570  mRate->Clear();
571  for (const auto &name : names)
572  mRate->Append( name.Translation() );
573 }
574 
575 //----------------------------------------------------------------------------
576 // FindDialog
577 //----------------------------------------------------------------------------
578 
579 #define ID_BROWSE 5000
580 #define ID_DLOAD 5001
581 
582 class FindDialog final : public wxDialogWrapper
583 {
584 public:
585 
586 #ifndef DISABLE_DYNAMIC_LOADING_LAME
587 
588  FindDialog(wxWindow *parent, wxString path, wxString name,
589  FileNames::FileTypes types)
590  : wxDialogWrapper(parent, wxID_ANY,
591  /* i18n-hint: LAME is the name of an MP3 converter and should not be translated*/
592  XO("Locate LAME"))
593  {
594  SetName();
595  ShuttleGui S(this, eIsCreating);
596 
597  mPath = path;
598  mName = name;
599  mTypes = std::move( types );
600 
601  mLibPath.Assign(mPath, mName);
602 
604  }
605 
607  {
608  S.SetBorder(10);
609  S.StartVerticalLay(true);
610  {
611  S.AddTitle(
612  XO("Audacity needs the file %s to create MP3s.")
613  .Format( mName ) );
614 
615  S.SetBorder(3);
616  S.StartHorizontalLay(wxALIGN_LEFT, true);
617  {
618  S.AddTitle( XO("Location of %s:").Format( mName ) );
619  }
620  S.EndHorizontalLay();
621 
622  S.StartMultiColumn(2, wxEXPAND);
623  S.SetStretchyCol(0);
624  {
625  if (mLibPath.GetFullPath().empty()) {
626  mPathText = S.AddTextBox( {},
627  /* i18n-hint: There is a button to the right of the arrow.*/
628  wxString::Format(_("To find %s, click here -->"), mName), 0);
629  }
630  else {
631  mPathText = S.AddTextBox( {}, mLibPath.GetFullPath(), 0);
632  }
633  S.Id(ID_BROWSE).AddButton(XXO("Browse..."), wxALIGN_RIGHT);
634  S.AddVariableText(
635  /* i18n-hint: There is a button to the right of the arrow.*/
636  XO("To get a free copy of LAME, click here -->"), true);
637  /* i18n-hint: (verb)*/
638  S.Id(ID_DLOAD).AddButton(XXO("Download"), wxALIGN_RIGHT);
639  }
640  S.EndMultiColumn();
641 
642  S.AddStandardButtons();
643  }
644  S.EndVerticalLay();
645 
646  Layout();
647  Fit();
648  SetMinSize(GetSize());
649  Center();
650 
651  return;
652  }
653 
654  void OnBrowse(wxCommandEvent & WXUNUSED(event))
655  {
656  /* i18n-hint: It's asking for the location of a file, for
657  * example, "Where is lame_enc.dll?" - you could translate
658  * "Where would I find the file %s" instead if you want. */
659  auto question = XO("Where is %s?").Format( mName );
660 
661  wxString path = FileNames::SelectFile(FileNames::Operation::_None,
662  question,
663  mLibPath.GetPath(),
664  mLibPath.GetName(),
665  wxT(""),
666  mTypes,
667  wxFD_OPEN | wxRESIZE_BORDER,
668  this);
669  if (!path.empty()) {
670  mLibPath = path;
671  mPathText->SetValue(path);
672  }
673  }
674 
675  void OnDownload(wxCommandEvent & WXUNUSED(event))
676  {
677  HelpSystem::ShowHelp(this, wxT("FAQ:Installing_the_LAME_MP3_Encoder"));
678  }
679 
680  wxString GetLibPath()
681  {
682  return mLibPath.GetFullPath();
683  }
684 
685 #endif // DISABLE_DYNAMIC_LOADING_LAME
686 
687 private:
688 
689 #ifndef DISABLE_DYNAMIC_LOADING_LAME
690  wxFileName mLibPath;
691 
692  wxString mPath;
693  wxString mName;
695 #endif // DISABLE_DYNAMIC_LOADING_LAME
696 
697  wxTextCtrl *mPathText;
698 
699  DECLARE_EVENT_TABLE()
700 };
701 
702 #ifndef DISABLE_DYNAMIC_LOADING_LAME
703 BEGIN_EVENT_TABLE(FindDialog, wxDialogWrapper)
707 #endif // DISABLE_DYNAMIC_LOADING_LAME
708 
709 //----------------------------------------------------------------------------
710 // MP3Exporter
711 //----------------------------------------------------------------------------
712 
713 #ifndef DISABLE_DYNAMIC_LOADING_LAME
714 
717 typedef const char* get_lame_version_t(void);
718 
720  lame_t gfp,
721  const float pcm_l[],
722  const float pcm_r[],
723  const int nsamples,
724  unsigned char * mp3buf,
725  const int mp3buf_size);
726 
728  lame_t gfp,
729  const float pcm[],
730  const int nsamples,
731  unsigned char * mp3buf,
732  const int mp3buf_size);
733 
735  lame_global_flags *gf,
736  unsigned char* mp3buf,
737  int size );
738 
740 
746 typedef int lame_set_VBR_t(lame_global_flags *, vbr_mode);
749 typedef int lame_set_mode_t(lame_global_flags *, MPEG_mode);
754 typedef size_t lame_get_lametag_frame_t(const lame_global_flags *, unsigned char* buffer, size_t size);
755 typedef void lame_mp3_tags_fid_t(lame_global_flags *, FILE *);
756 
757 #endif // DISABLE_DYNAMIC_LOADING_LAME
758 
759 #if defined(__WXMSW__)
760 // An alternative solution to give Windows an additional chance of writing the tag before
761 // falling bato to lame_mp3_tag_fid(). The latter can have DLL sharing issues when mixing
762 // Debug/Release builds of Audacity and the lame DLL.
763 typedef unsigned long beWriteInfoTag_t(lame_global_flags *, char *);
764 
765 // We use this to determine if the user has selected an older, Blade API only, lame_enc.dll
766 // so we can be more specific about why their library isn't acceptable.
767 typedef struct {
768 
769  // BladeEnc DLL Version number
770 
771  BYTE byDLLMajorVersion;
772  BYTE byDLLMinorVersion;
773 
774  // BladeEnc Engine Version Number
775 
776  BYTE byMajorVersion;
777  BYTE byMinorVersion;
778 
779  // DLL Release date
780 
781  BYTE byDay;
782  BYTE byMonth;
783  WORD wYear;
784 
785  // BladeEnc Homepage URL
786 
787  CHAR zHomepage[129];
788 
789  BYTE byAlphaLevel;
790  BYTE byBetaLevel;
791  BYTE byMMXEnabled;
792 
793  BYTE btReserved[125];
794 } be_version;
795 typedef void beVersion_t(be_version *);
796 #endif
797 
799 {
800 public:
801  enum AskUser
802  {
803  No,
805  Yes
806  };
807 
808  MP3Exporter();
809  ~MP3Exporter();
810 
811 #ifndef DISABLE_DYNAMIC_LOADING_LAME
812  bool FindLibrary(wxWindow *parent);
813  bool LoadLibrary(wxWindow *parent, AskUser askuser);
814  bool ValidLibraryLoaded();
815 #endif // DISABLE_DYNAMIC_LOADING_LAME
816 
817  /* These global settings keep state over the life of the object */
818  void SetMode(int mode);
819  void SetBitrate(int rate);
820  void SetQuality(int q/*, int r*/);
821  void SetChannel(int mode);
822 
823  /* Virtual methods that must be supplied by library interfaces */
824 
825  /* initialize the library interface */
826  bool InitLibrary(wxString libpath);
827  bool InitLibraryInternal();
828  bool InitLibraryExternal(wxString libpath);
829  void FreeLibrary();
830 
831  /* get library info */
832  wxString GetLibraryVersion();
833  wxString GetLibraryName();
834  wxString GetLibraryPath();
836 
837  /* returns the number of samples PER CHANNEL to send for each call to EncodeBuffer */
838  int InitializeStream(unsigned channels, int sampleRate);
839 
840  /* In bytes. must be called AFTER InitializeStream */
841  int GetOutBufferSize();
842 
843  /* returns the number of bytes written. input is interleaved if stereo*/
844  int EncodeBuffer(float inbuffer[], unsigned char outbuffer[]);
845  int EncodeRemainder(float inbuffer[], int nSamples,
846  unsigned char outbuffer[]);
847 
848  int EncodeBufferMono(float inbuffer[], unsigned char outbuffer[]);
849  int EncodeRemainderMono(float inbuffer[], int nSamples,
850  unsigned char outbuffer[]);
851 
852  int FinishStream(unsigned char outbuffer[]);
853  void CancelEncoding();
854 
855  bool PutInfoTag(wxFFile & f, wxFileOffset off);
856 
857 private:
859 
860 #ifndef DISABLE_DYNAMIC_LOADING_LAME
861  wxString mLibPath;
862  wxDynamicLibrary lame_lib;
864 #endif // DISABLE_DYNAMIC_LOADING_LAME
865 
866 #if defined(__WXMSW__)
867  TranslatableString mBladeVersion;
868 #endif
869 
870  bool mEncoding;
871  int mMode;
872  int mBitrate;
873  int mQuality;
874  //int mRoutine;
875  int mChannel;
876 
877 #ifndef DISABLE_DYNAMIC_LOADING_LAME
878  /* function pointers to the symbols we get from the library */
886 
902 #if defined(__WXMSW__)
903  beWriteInfoTag_t *beWriteInfoTag;
904  beVersion_t *beVersion;
905 #endif
906 #endif // DISABLE_DYNAMIC_LOADING_LAME
907 
909 
910  static const int mSamplesPerChunk = 220500;
911  // See lame.h/lame_encode_buffer() for further explanation
912  // As coded here, this should be the worst case.
913  static const int mOutBufferSize =
914  mSamplesPerChunk * (320 / 8) / 8 + 4 * 1152 * (320 / 8) / 8 + 512;
915 
916  // See MAXFRAMESIZE in libmp3lame/VbrTag.c for explanation of 2880.
917  unsigned char mInfoTagBuf[2880];
918  size_t mInfoTagLen;
919 };
920 
922 {
923 // We could use #defines rather than this variable.
924 // The idea of the variable is that if we wanted, we could allow
925 // a dynamic override of the library, e.g. with a newer faster version,
926 // or to fix CVEs in the underlying librray.
927 // for now though the 'variable' is a constant.
928 #ifdef MP3_EXPORT_BUILT_IN
929  mLibIsExternal = false;
930 #else
931  mLibIsExternal = true;
932 #endif
933 
934 #ifndef DISABLE_DYNAMIC_LOADING_LAME
935  mLibraryLoaded = false;
936 #endif // DISABLE_DYNAMIC_LOADING_LAME
937  mEncoding = false;
938  mGF = NULL;
939 
940 #ifndef DISABLE_DYNAMIC_LOADING_LAME
941  if (gPrefs) {
942  mLibPath = gPrefs->Read(wxT("/MP3/MP3LibPath"), wxT(""));
943  }
944 #endif // DISABLE_DYNAMIC_LOADING_LAME
945 
946  mBitrate = 128;
949  mMode = MODE_CBR;
950  //mRoutine = ROUTINE_FAST;
951 }
952 
954 {
955  FreeLibrary();
956 }
957 
958 #ifndef DISABLE_DYNAMIC_LOADING_LAME
959 
960 bool MP3Exporter::FindLibrary(wxWindow *parent)
961 {
962  wxString path;
963  wxString name;
964 
965  if (!mLibPath.empty()) {
966  wxFileName fn = mLibPath;
967  path = fn.GetPath();
968  name = fn.GetFullName();
969  }
970  else {
971  path = GetLibraryPath();
972  name = GetLibraryName();
973  }
974 
975  FindDialog fd(parent,
976  path,
977  name,
978  GetLibraryTypes());
979 
980  if (fd.ShowModal() == wxID_CANCEL) {
981  return false;
982  }
983 
984  path = fd.GetLibPath();
985 
986  if (!::wxFileExists(path)) {
987  return false;
988  }
989 
990  mLibPath = path;
991 
992  return (gPrefs->Write(wxT("/MP3/MP3LibPath"), mLibPath) && gPrefs->Flush());
993 }
994 
995 bool MP3Exporter::LoadLibrary(wxWindow *parent, AskUser askuser)
996 {
997 
998  if (ValidLibraryLoaded()) {
999  FreeLibrary();
1000  mLibraryLoaded = false;
1001  }
1002 
1003 #if defined(__WXMSW__)
1004  mBladeVersion = {};
1005 #endif
1006 
1007  if( !mLibIsExternal ){
1009  return mLibraryLoaded;
1010  }
1011 
1012  // First try loading it from a previously located path
1013  if (!mLibPath.empty()) {
1014  wxLogMessage(wxT("Attempting to load LAME from previously defined path"));
1016  }
1017 
1018  // If not successful, try loading using system search paths
1019  if (!ValidLibraryLoaded()) {
1020  wxLogMessage(wxT("Attempting to load LAME from system search paths"));
1023  }
1024 
1025  // If not successful, try loading using compiled in path
1026  if (!ValidLibraryLoaded()) {
1027  wxLogMessage(wxT("Attempting to load LAME from builtin path"));
1028  wxFileName fn(GetLibraryPath(), GetLibraryName());
1029  mLibPath = fn.GetFullPath();
1031  }
1032 
1033  // If not successful, must ask the user
1034  if (!ValidLibraryLoaded()) {
1035  wxLogMessage(wxT("(Maybe) ask user for library"));
1036  if (askuser == MP3Exporter::Maybe && FindLibrary(parent)) {
1038  }
1039  }
1040 
1041  // Oh well, just give up
1042  if (!ValidLibraryLoaded()) {
1043 #if defined(__WXMSW__)
1044  if (askuser && !mBladeVersion.empty()) {
1045  AudacityMessageBox( mBladeVersion );
1046  }
1047 #endif
1048  wxLogMessage(wxT("Failed to locate LAME library"));
1049 
1050  return false;
1051  }
1052 
1053  wxLogMessage(wxT("LAME library successfully loaded"));
1054 
1055  return true;
1056 }
1057 
1059 {
1060  return mLibraryLoaded;
1061 }
1062 
1063 #endif // DISABLE_DYNAMIC_LOADING_LAME
1064 
1065 void MP3Exporter::SetMode(int mode)
1066 {
1067  mMode = mode;
1068 }
1069 
1071 {
1072  mBitrate = rate;
1073 }
1074 
1075 void MP3Exporter::SetQuality(int q/*, int r*/)
1076 {
1077  mQuality = q;
1078  //mRoutine = r;
1079 }
1080 
1082 {
1083  mChannel = mode;
1084 }
1085 
1086 bool MP3Exporter::InitLibrary(wxString libpath)
1087 {
1089 }
1090 
1092 {
1093  wxLogMessage(wxT("Using internal LAME"));
1094 
1095 // The global ::lame_something symbols only exist if LAME is built in.
1096 // So we don't reference them unless they are.
1097 #ifdef MP3_EXPORT_BUILT_IN
1098 
1106 
1120 
1121  // These are optional
1122  //lame_get_lametag_frame = ::lame_get_lametag_frame;
1123  lame_get_lametag_frame = NULL;
1125 
1126 #if defined(__WXMSW__)
1127  //beWriteInfoTag = ::beWriteInfoTag;
1128  //beVersion = ::beVersion;
1129  beWriteInfoTag = NULL;
1130  beVersion = NULL;
1131 #endif
1132 
1133  mGF = lame_init();
1134  if (mGF == NULL) {
1135  return false;
1136  }
1137 #endif
1138 
1139  return true;
1140 }
1141 
1142 
1143 bool MP3Exporter::InitLibraryExternal(wxString libpath)
1144 {
1145  wxLogMessage(wxT("Loading LAME from %s"), libpath);
1146 
1147 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1148  if (!lame_lib.Load(libpath, wxDL_LAZY)) {
1149  wxLogMessage(wxT("load failed"));
1150  return false;
1151  }
1152 
1153  wxLogMessage(wxT("Actual LAME path %s"),
1154  FileNames::PathFromAddr(lame_lib.GetSymbol(wxT("lame_init"))));
1155 
1156  lame_init = (lame_init_t *)
1157  lame_lib.GetSymbol(wxT("lame_init"));
1159  lame_lib.GetSymbol(wxT("get_lame_version"));
1161  lame_lib.GetSymbol(wxT("lame_init_params"));
1163  lame_lib.GetSymbol(wxT("lame_encode_buffer_ieee_float"));
1165  lame_lib.GetSymbol(wxT("lame_encode_buffer_interleaved_ieee_float"));
1167  lame_lib.GetSymbol(wxT("lame_encode_flush"));
1168  lame_close = (lame_close_t *)
1169  lame_lib.GetSymbol(wxT("lame_close"));
1170 
1172  lame_lib.GetSymbol(wxT("lame_set_in_samplerate"));
1174  lame_lib.GetSymbol(wxT("lame_set_out_samplerate"));
1176  lame_lib.GetSymbol(wxT("lame_set_num_channels"));
1178  lame_lib.GetSymbol(wxT("lame_set_quality"));
1180  lame_lib.GetSymbol(wxT("lame_set_brate"));
1182  lame_lib.GetSymbol(wxT("lame_set_VBR"));
1184  lame_lib.GetSymbol(wxT("lame_set_VBR_q"));
1186  lame_lib.GetSymbol(wxT("lame_set_VBR_min_bitrate_kbps"));
1188  lame_lib.GetSymbol(wxT("lame_set_mode"));
1190  lame_lib.GetSymbol(wxT("lame_set_preset"));
1192  lame_lib.GetSymbol(wxT("lame_set_error_protection"));
1194  lame_lib.GetSymbol(wxT("lame_set_disable_reservoir"));
1196  lame_lib.GetSymbol(wxT("lame_set_bWriteVbrTag"));
1197 
1198  // These are optional
1200  lame_lib.GetSymbol(wxT("lame_get_lametag_frame"));
1202  lame_lib.GetSymbol(wxT("lame_mp3_tags_fid"));
1203 #if defined(__WXMSW__)
1204  beWriteInfoTag = (beWriteInfoTag_t *)
1205  lame_lib.GetSymbol(wxT("beWriteInfoTag"));
1206  beVersion = (beVersion_t *)
1207  lame_lib.GetSymbol(wxT("beVersion"));
1208 #endif
1209 
1210  if (!lame_init ||
1211  !get_lame_version ||
1212  !lame_init_params ||
1215  !lame_encode_flush ||
1216  !lame_close ||
1220  !lame_set_quality ||
1221  !lame_set_brate ||
1222  !lame_set_VBR ||
1223  !lame_set_VBR_q ||
1224  !lame_set_mode ||
1225  !lame_set_preset ||
1229  {
1230  wxLogMessage(wxT("Failed to find a required symbol in the LAME library."));
1231 #if defined(__WXMSW__)
1232  if (beVersion) {
1233  be_version v;
1234  beVersion(&v);
1235 
1236  mBladeVersion = XO(
1237 "You are linking to lame_enc.dll v%d.%d. This version is not compatible with Audacity %d.%d.%d.\nPlease download the latest version of 'LAME for Audacity'.")
1238  .Format(
1239  v.byMajorVersion,
1240  v.byMinorVersion,
1241  AUDACITY_VERSION,
1242  AUDACITY_RELEASE,
1243  AUDACITY_REVISION);
1244  }
1245 #endif
1246 
1247  lame_lib.Unload();
1248  return false;
1249  }
1250 #endif // DISABLE_DYNAMIC_LOADING_LAME
1251 
1252  mGF = lame_init();
1253  if (mGF == NULL) {
1254  return false;
1255  }
1256 
1257  return true;
1258 }
1259 
1261 {
1262  if (mGF) {
1263  lame_close(mGF);
1264  mGF = NULL;
1265  }
1266 
1267 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1268  lame_lib.Unload();
1269 #endif // DISABLE_DYNAMIC_LOADING_LAME
1270 
1271  return;
1272 }
1273 
1275 {
1276 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1277  if (!mLibraryLoaded) {
1278  return wxT("");
1279  }
1280 #endif // DISABLE_DYNAMIC_LOADING_LAME
1281 
1282  return wxString::Format(wxT("LAME %hs"), get_lame_version());
1283 }
1284 
1285 int MP3Exporter::InitializeStream(unsigned channels, int sampleRate)
1286 {
1287 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1288  if (!mLibraryLoaded) {
1289  return -1;
1290  }
1291 #endif // DISABLE_DYNAMIC_LOADING_LAME
1292 
1293  if (channels > 2) {
1294  return -1;
1295  }
1296 
1298  lame_set_num_channels(mGF, channels);
1299  lame_set_in_samplerate(mGF, sampleRate);
1300  lame_set_out_samplerate(mGF, sampleRate);
1302  // Add the VbrTag for all types. For ABR/VBR, a Xing tag will be created.
1303  // For CBR, it will be a Lame Info tag.
1304  lame_set_bWriteVbrTag(mGF, true);
1305 
1306  // Set the VBR quality or ABR/CBR bitrate
1307  switch (mMode) {
1308  case MODE_SET:
1309  {
1310  int preset;
1311 
1312  if (mQuality == PRESET_INSANE) {
1313  preset = INSANE;
1314  }
1315  //else if (mRoutine == ROUTINE_FAST) {
1316  else if (mQuality == PRESET_EXTREME) {
1317  preset = EXTREME_FAST;
1318  }
1319  else if (mQuality == PRESET_STANDARD) {
1320  preset = STANDARD_FAST;
1321  }
1322  else {
1323  preset = 1007; // Not defined until 3.96
1324  }
1325  //}
1326  /*
1327  else {
1328  if (mQuality == PRESET_EXTREME) {
1329  preset = EXTREME;
1330  }
1331  else if (mQuality == PRESET_STANDARD) {
1332  preset = STANDARD;
1333  }
1334  else {
1335  preset = 1006; // Not defined until 3.96
1336  }
1337  }
1338  */
1339  lame_set_preset(mGF, preset);
1340  }
1341  break;
1342 
1343  case MODE_VBR:
1344  lame_set_VBR(mGF, vbr_mtrh );
1346  break;
1347 
1348  case MODE_ABR:
1350  break;
1351 
1352  default:
1353  lame_set_VBR(mGF, vbr_off);
1355  break;
1356  }
1357 
1358  // Set the channel mode
1359  MPEG_mode mode;
1360 
1361  if (channels == 1 || mChannel == CHANNEL_MONO) {
1362  mode = MONO;
1363  }
1364  else if (mChannel == CHANNEL_JOINT) {
1365  mode = JOINT_STEREO;
1366  }
1367  else {
1368  mode = STEREO;
1369  }
1370  lame_set_mode(mGF, mode);
1371 
1372  int rc = lame_init_params(mGF);
1373  if (rc < 0) {
1374  return rc;
1375  }
1376 
1377 #if 0
1378  dump_config(mGF);
1379 #endif
1380 
1381  mInfoTagLen = 0;
1382  mEncoding = true;
1383 
1384  return mSamplesPerChunk;
1385 }
1386 
1388 {
1389  if (!mEncoding)
1390  return -1;
1391 
1392  return mOutBufferSize;
1393 }
1394 
1395 int MP3Exporter::EncodeBuffer(float inbuffer[], unsigned char outbuffer[])
1396 {
1397  if (!mEncoding) {
1398  return -1;
1399  }
1400 
1402  outbuffer, mOutBufferSize);
1403 }
1404 
1405 int MP3Exporter::EncodeRemainder(float inbuffer[], int nSamples,
1406  unsigned char outbuffer[])
1407 {
1408  if (!mEncoding) {
1409  return -1;
1410  }
1411 
1412  return lame_encode_buffer_interleaved_ieee_float(mGF, inbuffer, nSamples, outbuffer,
1413  mOutBufferSize);
1414 }
1415 
1416 int MP3Exporter::EncodeBufferMono(float inbuffer[], unsigned char outbuffer[])
1417 {
1418  if (!mEncoding) {
1419  return -1;
1420  }
1421 
1422  return lame_encode_buffer_ieee_float(mGF, inbuffer,inbuffer, mSamplesPerChunk,
1423  outbuffer, mOutBufferSize);
1424 }
1425 
1426 int MP3Exporter::EncodeRemainderMono(float inbuffer[], int nSamples,
1427  unsigned char outbuffer[])
1428 {
1429  if (!mEncoding) {
1430  return -1;
1431  }
1432 
1433  return lame_encode_buffer_ieee_float(mGF, inbuffer, inbuffer, nSamples, outbuffer,
1434  mOutBufferSize);
1435 }
1436 
1437 int MP3Exporter::FinishStream(unsigned char outbuffer[])
1438 {
1439  if (!mEncoding) {
1440  return -1;
1441  }
1442 
1443  mEncoding = false;
1444 
1445  int result = lame_encode_flush(mGF, outbuffer, mOutBufferSize);
1446 
1447 #if defined(DISABLE_DYNAMIC_LOADING_LAME)
1449 #else
1450  if (lame_get_lametag_frame) {
1452  }
1453 #endif
1454 
1455  return result;
1456 }
1457 
1459 {
1460  mEncoding = false;
1461 }
1462 
1463 bool MP3Exporter::PutInfoTag(wxFFile & f, wxFileOffset off)
1464 {
1465  if (mGF) {
1466  if (mInfoTagLen > 0) {
1467  // FIXME: TRAP_ERR Seek and writ ein MP3 exporter could fail.
1468  if ( !f.Seek(off, wxFromStart))
1469  return false;
1470  if (mInfoTagLen > f.Write(mInfoTagBuf, mInfoTagLen))
1471  return false;
1472  }
1473 #if defined(__WXMSW__)
1474  else if (beWriteInfoTag) {
1475  if ( !f.Flush() )
1476  return false;
1477  // PRL: What is the correct error check on the return value?
1478  beWriteInfoTag(mGF, OSOUTPUT(f.GetName()));
1479  mGF = NULL;
1480  }
1481 #endif
1482  else if (lame_mp3_tags_fid != NULL) {
1483  lame_mp3_tags_fid(mGF, f.fp());
1484  }
1485  }
1486 
1487  if ( !f.SeekEnd() )
1488  return false;
1489 
1490  return true;
1491 }
1492 
1493 #if defined(__WXMSW__)
1494 /* values for Windows */
1495 
1496 wxString MP3Exporter::GetLibraryPath()
1497 {
1498  wxRegKey reg(wxT("HKEY_LOCAL_MACHINE\\Software\\Lame for Audacity"));
1499  wxString path;
1500 
1501  if (reg.Exists()) {
1502  wxLogMessage(wxT("LAME registry key exists."));
1503  reg.QueryValue(wxT("InstallPath"), path);
1504  }
1505  else {
1506  wxLogMessage(wxT("LAME registry key does not exist."));
1507  }
1508 
1509  wxLogMessage(wxT("Library path is: ") + path);
1510 
1511  return path;
1512 }
1513 
1514 wxString MP3Exporter::GetLibraryName()
1515 {
1516  return wxT("lame_enc.dll");
1517 }
1518 
1520 {
1521  return {
1522  { XO("Only lame_enc.dll"), { wxT("lame_enc.dll") } },
1525  };
1526 }
1527 
1528 #elif defined(__WXMAC__)
1529 /* values for Mac OS X */
1530 
1531 wxString MP3Exporter::GetLibraryPath()
1532 {
1533  wxString path;
1534 
1535  path = wxT("/Library/Application Support/audacity/libs");
1536  if (wxFileExists(path + wxT("/") + GetLibraryName()))
1537  {
1538  return path;
1539  }
1540 
1541  path = wxT("/usr/local/lib/audacity");
1542  if (wxFileExists(path + wxT("/") + GetLibraryName()))
1543  {
1544  return path;
1545  }
1546 
1547  return wxT("/Library/Application Support/audacity/libs");
1548 }
1549 
1550 wxString MP3Exporter::GetLibraryName()
1551 {
1552  if (sizeof(void*) == 8)
1553  return wxT("libmp3lame64bit.dylib");
1554  return wxT("libmp3lame.dylib");
1555 }
1556 
1558 {
1559  return {
1560  (sizeof(void*) == 8)
1562  XO("Only libmp3lame64bit.dylib"), { wxT("libmp3lame64bit.dylib") }
1563  }
1565  XO("Only libmp3lame.dylib"), { wxT("libmp3lame.dylib") }
1566  }
1567  ,
1570  };
1571 }
1572 
1573 #else
1574 /* Values for Linux / Unix systems */
1575 
1577 {
1578  return wxT(LIBDIR);
1579 }
1580 
1582 {
1583  return wxT("libmp3lame.so.0");
1584 }
1585 
1587 {
1588  return {
1589  { XO("Only libmp3lame.so.0"), { wxT("libmp3lame.so.0") } },
1590  { XO("Primary shared object files"), { wxT("so") }, true },
1591  { XO("Extended libraries"), { wxT("so*") }, true },
1593  };
1594 }
1595 #endif
1596 
1597 #if 0
1598 // Debug routine from BladeMP3EncDLL.c in the libmp3lame distro
1599 static void dump_config( lame_global_flags* gfp )
1600 {
1601  wxPrintf(wxT("\n\nLame_enc configuration options:\n"));
1602  wxPrintf(wxT("==========================================================\n"));
1603 
1604  wxPrintf(wxT("version =%d\n"),lame_get_version( gfp ) );
1605  wxPrintf(wxT("Layer =3\n"));
1606  wxPrintf(wxT("mode ="));
1607  switch ( lame_get_mode( gfp ) )
1608  {
1609  case STEREO: wxPrintf(wxT( "Stereo\n" )); break;
1610  case JOINT_STEREO: wxPrintf(wxT( "Joint-Stereo\n" )); break;
1611  case DUAL_CHANNEL: wxPrintf(wxT( "Forced Stereo\n" )); break;
1612  case MONO: wxPrintf(wxT( "Mono\n" )); break;
1613  case NOT_SET: /* FALLTHROUGH */
1614  default: wxPrintf(wxT( "Error (unknown)\n" )); break;
1615  }
1616 
1617  wxPrintf(wxT("Input sample rate =%.1f kHz\n"), lame_get_in_samplerate( gfp ) /1000.0 );
1618  wxPrintf(wxT("Output sample rate =%.1f kHz\n"), lame_get_out_samplerate( gfp ) /1000.0 );
1619 
1620  wxPrintf(wxT("bitrate =%d kbps\n"), lame_get_brate( gfp ) );
1621  wxPrintf(wxT("Quality Setting =%d\n"), lame_get_quality( gfp ) );
1622 
1623  wxPrintf(wxT("Low pass frequency =%d\n"), lame_get_lowpassfreq( gfp ) );
1624  wxPrintf(wxT("Low pass width =%d\n"), lame_get_lowpasswidth( gfp ) );
1625 
1626  wxPrintf(wxT("High pass frequency =%d\n"), lame_get_highpassfreq( gfp ) );
1627  wxPrintf(wxT("High pass width =%d\n"), lame_get_highpasswidth( gfp ) );
1628 
1629  wxPrintf(wxT("No short blocks =%d\n"), lame_get_no_short_blocks( gfp ) );
1630  wxPrintf(wxT("Force short blocks =%d\n"), lame_get_force_short_blocks( gfp ) );
1631 
1632  wxPrintf(wxT("de-emphasis =%d\n"), lame_get_emphasis( gfp ) );
1633  wxPrintf(wxT("private flag =%d\n"), lame_get_extension( gfp ) );
1634 
1635  wxPrintf(wxT("copyright flag =%d\n"), lame_get_copyright( gfp ) );
1636  wxPrintf(wxT("original flag =%d\n"), lame_get_original( gfp ) );
1637  wxPrintf(wxT("CRC =%s\n"), lame_get_error_protection( gfp ) ? wxT("on") : wxT("off") );
1638  wxPrintf(wxT("Fast mode =%s\n"), ( lame_get_quality( gfp ) )? wxT("enabled") : wxT("disabled") );
1639  wxPrintf(wxT("Force mid/side stereo =%s\n"), ( lame_get_force_ms( gfp ) )?wxT("enabled"):wxT("disabled") );
1640  wxPrintf(wxT("Padding Type =%d\n"), (int) lame_get_padding_type( gfp ) );
1641  wxPrintf(wxT("Disable Reservoir =%d\n"), lame_get_disable_reservoir( gfp ) );
1642  wxPrintf(wxT("Allow diff-short =%d\n"), lame_get_allow_diff_short( gfp ) );
1643  wxPrintf(wxT("Interchannel masking =%d\n"), lame_get_interChRatio( gfp ) ); // supposed to be a float, but in lib-src/lame/lame/lame.h it's int
1644  wxPrintf(wxT("Strict ISO Encoding =%s\n"), ( lame_get_strict_ISO( gfp ) ) ?wxT("Yes"):wxT("No"));
1645  wxPrintf(wxT("Scale =%5.2f\n"), lame_get_scale( gfp ) );
1646 
1647  wxPrintf(wxT("VBR =%s, VBR_q =%d, VBR method ="),
1648  ( lame_get_VBR( gfp ) !=vbr_off ) ? wxT("enabled"): wxT("disabled"),
1649  lame_get_VBR_q( gfp ) );
1650 
1651  switch ( lame_get_VBR( gfp ) )
1652  {
1653  case vbr_off: wxPrintf(wxT( "vbr_off\n" )); break;
1654  case vbr_mt : wxPrintf(wxT( "vbr_mt \n" )); break;
1655  case vbr_rh : wxPrintf(wxT( "vbr_rh \n" )); break;
1656  case vbr_mtrh: wxPrintf(wxT( "vbr_mtrh \n" )); break;
1657  case vbr_abr:
1658  wxPrintf(wxT( "vbr_abr (average bitrate %d kbps)\n"), lame_get_VBR_mean_bitrate_kbps( gfp ) );
1659  break;
1660  default:
1661  wxPrintf(wxT("error, unknown VBR setting\n"));
1662  break;
1663  }
1664 
1665  wxPrintf(wxT("Vbr Min bitrate =%d kbps\n"), lame_get_VBR_min_bitrate_kbps( gfp ) );
1666  wxPrintf(wxT("Vbr Max bitrate =%d kbps\n"), lame_get_VBR_max_bitrate_kbps( gfp ) );
1667 
1668  wxPrintf(wxT("Write VBR Header =%s\n"), ( lame_get_bWriteVbrTag( gfp ) ) ?wxT("Yes"):wxT("No"));
1669  wxPrintf(wxT("VBR Hard min =%d\n"), lame_get_VBR_hard_min( gfp ) );
1670 
1671  wxPrintf(wxT("ATH Only =%d\n"), lame_get_ATHonly( gfp ) );
1672  wxPrintf(wxT("ATH short =%d\n"), lame_get_ATHshort( gfp ) );
1673  wxPrintf(wxT("ATH no =%d\n"), lame_get_noATH( gfp ) );
1674  wxPrintf(wxT("ATH type =%d\n"), lame_get_ATHtype( gfp ) );
1675  wxPrintf(wxT("ATH lower =%f\n"), lame_get_ATHlower( gfp ) );
1676  wxPrintf(wxT("ATH aa =%d\n"), lame_get_athaa_type( gfp ) );
1677  wxPrintf(wxT("ATH aa loudapprox =%d\n"), lame_get_athaa_loudapprox( gfp ) );
1678  wxPrintf(wxT("ATH aa sensitivity =%f\n"), lame_get_athaa_sensitivity( gfp ) );
1679 
1680  wxPrintf(wxT("Experimental nspsytune =%d\n"), lame_get_exp_nspsytune( gfp ) );
1681  wxPrintf(wxT("Experimental X =%d\n"), lame_get_experimentalX( gfp ) );
1682  wxPrintf(wxT("Experimental Y =%d\n"), lame_get_experimentalY( gfp ) );
1683  wxPrintf(wxT("Experimental Z =%d\n"), lame_get_experimentalZ( gfp ) );
1684 }
1685 #endif
1686 
1687 //----------------------------------------------------------------------------
1688 // ExportMP3
1689 //----------------------------------------------------------------------------
1690 
1691 class ExportMP3 final : public ExportPlugin
1692 {
1693 public:
1694 
1695  ExportMP3();
1696  bool CheckFileName(wxFileName & filename, int format) override;
1697 
1698  // Required
1699 
1700  void OptionsCreate(ShuttleGui &S, int format) override;
1702  std::unique_ptr<ProgressDialog> &pDialog,
1703  unsigned channels,
1704  const wxFileNameWrapper &fName,
1705  bool selectedOnly,
1706  double t0,
1707  double t1,
1708  MixerSpec *mixerSpec = NULL,
1709  const Tags *metadata = NULL,
1710  int subformat = 0) override;
1711 
1712 private:
1713 
1714  int AskResample(int bitrate, int rate, int lowrate, int highrate);
1715  unsigned long AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
1716 #ifdef USE_LIBID3TAG
1717  void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
1718 #endif
1719  int SetNumExportChannels() override;
1720 };
1721 
1723 : ExportPlugin()
1724 {
1725  AddFormat();
1726  SetFormat(wxT("MP3"),0);
1727  AddExtension(wxT("mp3"),0);
1728  SetMaxChannels(2,0);
1729  SetCanMetaData(true,0);
1730  SetDescription(XO("MP3 Files"),0);
1731 }
1732 
1733 bool ExportMP3::CheckFileName(wxFileName & WXUNUSED(filename), int WXUNUSED(format))
1734 {
1735 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1736  MP3Exporter exporter;
1737 
1738  if (!exporter.LoadLibrary(wxTheApp->GetTopWindow(), MP3Exporter::Maybe)) {
1739  AudacityMessageBox( XO("Could not open MP3 encoding library!") );
1740  gPrefs->Write(wxT("/MP3/MP3LibPath"), wxString(wxT("")));
1741  gPrefs->Flush();
1742 
1743  return false;
1744  }
1745 #endif // DISABLE_DYNAMIC_LOADING_LAME
1746 
1747  return true;
1748 }
1749 
1751 {
1752  bool mono;
1753  gPrefs->Read(wxT("/FileFormats/MP3ForceMono"), &mono, 0);
1754 
1755  return (mono)? 1 : -1;
1756 }
1757 
1758 
1760  std::unique_ptr<ProgressDialog> &pDialog,
1761  unsigned channels,
1762  const wxFileNameWrapper &fName,
1763  bool selectionOnly,
1764  double t0,
1765  double t1,
1766  MixerSpec *mixerSpec,
1767  const Tags *metadata,
1768  int WXUNUSED(subformat))
1769 {
1770  int rate = lrint( ProjectSettings::Get( *project ).GetRate());
1771 #ifndef DISABLE_DYNAMIC_LOADING_LAME
1772  wxWindow *parent = ProjectWindow::Find( project );
1773 #endif // DISABLE_DYNAMIC_LOADING_LAME
1774  const auto &tracks = TrackList::Get( *project );
1775  MP3Exporter exporter;
1776 
1777 #ifdef DISABLE_DYNAMIC_LOADING_LAME
1778  if (!exporter.InitLibrary(wxT(""))) {
1779  AudacityMessageBox( XO("Could not initialize MP3 encoding library!") );
1780  gPrefs->Write(wxT("/MP3/MP3LibPath"), wxString(wxT("")));
1781  gPrefs->Flush();
1782 
1784  }
1785 #else
1786  if (!exporter.LoadLibrary(parent, MP3Exporter::Maybe)) {
1787  AudacityMessageBox( XO("Could not open MP3 encoding library!") );
1788  gPrefs->Write(wxT("/MP3/MP3LibPath"), wxString(wxT("")));
1789  gPrefs->Flush();
1790 
1792  }
1793 
1794  if (!exporter.ValidLibraryLoaded()) {
1795  AudacityMessageBox( XO("Not a valid or supported MP3 encoding library!") );
1796  gPrefs->Write(wxT("/MP3/MP3LibPath"), wxString(wxT("")));
1797  gPrefs->Flush();
1798 
1800  }
1801 #endif // DISABLE_DYNAMIC_LOADING_LAME
1802 
1803  // Retrieve preferences
1804  int highrate = 48000;
1805  int lowrate = 8000;
1806  int bitrate = 0;
1807  int brate;
1808  //int vmode;
1809  bool forceMono;
1810 
1811  gPrefs->Read(wxT("/FileFormats/MP3Bitrate"), &brate, 128);
1812  auto rmode = MP3RateModeSetting.ReadEnumWithDefault( MODE_CBR );
1813  //gPrefs->Read(wxT("/FileFormats/MP3VarMode"), &vmode, ROUTINE_FAST);
1814  auto cmode = MP3ChannelModeSetting.ReadEnumWithDefault( CHANNEL_STEREO );
1815  gPrefs->Read(wxT("/FileFormats/MP3ForceMono"), &forceMono, 0);
1816 
1817  // Set the bitrate/quality and mode
1818  if (rmode == MODE_SET) {
1819  brate = ValidateValue(setRateNames.size(), brate, PRESET_STANDARD);
1820  //int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST );
1821  exporter.SetMode(MODE_SET);
1822  exporter.SetQuality(brate/*, r*/);
1823  }
1824  else if (rmode == MODE_VBR) {
1825  brate = ValidateValue( varRateNames.size(), brate, QUALITY_2 );
1826  //int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST );
1827  exporter.SetMode(MODE_VBR);
1828  exporter.SetQuality(brate/*, r*/);
1829  }
1830  else if (rmode == MODE_ABR) {
1831  brate = ValidateIndex( fixRateValues, brate, 6 /* 128 kbps */ );
1832  bitrate = fixRateValues[ brate ];
1833  exporter.SetMode(MODE_ABR);
1834  exporter.SetBitrate(bitrate);
1835 
1836  if (bitrate > 160) {
1837  lowrate = 32000;
1838  }
1839  else if (bitrate < 32 || bitrate == 144) {
1840  highrate = 24000;
1841  }
1842  }
1843  else {
1844  brate = ValidateIndex( fixRateValues, brate, 6 /* 128 kbps */ );
1845  bitrate = fixRateValues[ brate ];
1846  exporter.SetMode(MODE_CBR);
1847  exporter.SetBitrate(bitrate);
1848 
1849  if (bitrate > 160) {
1850  lowrate = 32000;
1851  }
1852  else if (bitrate < 32 || bitrate == 144) {
1853  highrate = 24000;
1854  }
1855  }
1856 
1857  // Verify sample rate
1858  if (!make_iterator_range( sampRates ).contains( rate ) ||
1859  (rate < lowrate) || (rate > highrate)) {
1860  rate = AskResample(bitrate, rate, lowrate, highrate);
1861  if (rate == 0) {
1863  }
1864  }
1865 
1866  // Set the channel mode
1867  if (forceMono) {
1868  exporter.SetChannel(CHANNEL_MONO);
1869  }
1870  else if (cmode == CHANNEL_JOINT) {
1871  exporter.SetChannel(CHANNEL_JOINT);
1872  }
1873  else {
1874  exporter.SetChannel(CHANNEL_STEREO);
1875  }
1876 
1877  auto inSamples = exporter.InitializeStream(channels, rate);
1878  if (((int)inSamples) < 0) {
1879  AudacityMessageBox( XO("Unable to initialize MP3 stream") );
1881  }
1882 
1883  // Put ID3 tags at beginning of file
1884  if (metadata == NULL)
1885  metadata = &Tags::Get( *project );
1886 
1887  // Open file for writing
1888  wxFFile outFile(fName.GetFullPath(), wxT("w+b"));
1889  if (!outFile.IsOpened()) {
1890  AudacityMessageBox( XO("Unable to open target file for writing") );
1892  }
1893 
1894  ArrayOf<char> id3buffer;
1895  bool endOfFile;
1896  unsigned long id3len = AddTags(project, id3buffer, &endOfFile, metadata);
1897  if (id3len && !endOfFile) {
1898  if (id3len > outFile.Write(id3buffer.get(), id3len)) {
1899  // TODO: more precise message
1900  ShowExportErrorDialog("MP3:1882");
1902  }
1903  }
1904 
1905  wxFileOffset pos = outFile.Tell();
1906  auto updateResult = ProgressResult::Success;
1907  int bytes = 0;
1908 
1909  size_t bufferSize = std::max(0, exporter.GetOutBufferSize());
1910  if (bufferSize <= 0) {
1911  // TODO: more precise message
1912  ShowExportErrorDialog("MP3:1849");
1914  }
1915 
1916  ArrayOf<unsigned char> buffer{ bufferSize };
1917  wxASSERT(buffer);
1918 
1919  {
1920  auto mixer = CreateMixer(tracks, selectionOnly,
1921  t0, t1,
1922  channels, inSamples, true,
1923  rate, floatSample, mixerSpec);
1924 
1925  TranslatableString title;
1926  if (rmode == MODE_SET) {
1927  title = (selectionOnly ?
1928  XO("Exporting selected audio with %s preset") :
1929  XO("Exporting the audio with %s preset"))
1930  .Format( setRateNamesShort[brate] );
1931  }
1932  else if (rmode == MODE_VBR) {
1933  title = (selectionOnly ?
1934  XO("Exporting selected audio with VBR quality %s") :
1935  XO("Exporting the audio with VBR quality %s"))
1936  .Format( varRateNames[brate] );
1937  }
1938  else {
1939  title = (selectionOnly ?
1940  XO("Exporting selected audio at %d Kbps") :
1941  XO("Exporting the audio at %d Kbps"))
1942  .Format( bitrate );
1943  }
1944 
1945  InitProgress( pDialog, fName, title );
1946  auto &progress = *pDialog;
1947 
1948  while (updateResult == ProgressResult::Success) {
1949  auto blockLen = mixer->Process(inSamples);
1950 
1951  if (blockLen == 0) {
1952  break;
1953  }
1954 
1955  float *mixed = (float *)mixer->GetBuffer();
1956 
1957  if ((int)blockLen < inSamples) {
1958  if (channels > 1) {
1959  bytes = exporter.EncodeRemainder(mixed, blockLen, buffer.get());
1960  }
1961  else {
1962  bytes = exporter.EncodeRemainderMono(mixed, blockLen, buffer.get());
1963  }
1964  }
1965  else {
1966  if (channels > 1) {
1967  bytes = exporter.EncodeBuffer(mixed, buffer.get());
1968  }
1969  else {
1970  bytes = exporter.EncodeBufferMono(mixed, buffer.get());
1971  }
1972  }
1973 
1974  if (bytes < 0) {
1975  auto msg = XO("Error %ld returned from MP3 encoder")
1976  .Format( bytes );
1977  AudacityMessageBox( msg );
1978  updateResult = ProgressResult::Cancelled;
1979  break;
1980  }
1981 
1982  if (bytes > (int)outFile.Write(buffer.get(), bytes)) {
1983  // TODO: more precise message
1985  updateResult = ProgressResult::Cancelled;
1986  break;
1987  }
1988 
1989  updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
1990  }
1991  }
1992 
1993  if ( updateResult == ProgressResult::Success ||
1994  updateResult == ProgressResult::Stopped ) {
1995  bytes = exporter.FinishStream(buffer.get());
1996 
1997  if (bytes < 0) {
1998  // TODO: more precise message
1999  ShowExportErrorDialog("MP3:1981");
2001  }
2002 
2003  if (bytes > 0) {
2004  if (bytes > (int)outFile.Write(buffer.get(), bytes)) {
2005  // TODO: more precise message
2006  ShowExportErrorDialog("MP3:1988");
2008  }
2009  }
2010 
2011  // Write ID3 tag if it was supposed to be at the end of the file
2012  if (id3len > 0 && endOfFile) {
2013  if (bytes > (int)outFile.Write(id3buffer.get(), id3len)) {
2014  // TODO: more precise message
2015  ShowExportErrorDialog("MP3:1997");
2017  }
2018  }
2019 
2020  // Always write the info (Xing/Lame) tag. Until we stop supporting Lame
2021  // versions before 3.98, we must do this after the MP3 file has been
2022  // closed.
2023  //
2024  // Also, if beWriteInfoTag() is used, mGF will no longer be valid after
2025  // this call, so do not use it.
2026  if (!exporter.PutInfoTag(outFile, pos) ||
2027  !outFile.Flush() ||
2028  !outFile.Close()) {
2029  // TODO: more precise message
2030  ShowExportErrorDialog("MP3:2012");
2032  }
2033  }
2034 
2035  return updateResult;
2036 }
2037 
2039 {
2041 }
2042 
2043 int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate)
2044 {
2045  wxDialogWrapper d(nullptr, wxID_ANY, XO("Invalid sample rate"));
2046  d.SetName();
2047  wxChoice *choice;
2048  ShuttleGui S(&d, eIsCreating);
2049 
2050  int selected = -1;
2051 
2052  S.StartVerticalLay();
2053  {
2054  S.SetBorder(10);
2055  S.StartStatic(XO("Resample"));
2056  {
2057  S.StartHorizontalLay(wxALIGN_CENTER, false);
2058  {
2059  S.AddTitle(
2060  ((bitrate == 0)
2061  ? XO(
2062 "The project sample rate (%d) is not supported by the MP3\nfile format. ")
2063  .Format( rate )
2064  : XO(
2065 "The project sample rate (%d) and bit rate (%d kbps) combination is not\nsupported by the MP3 file format. ")
2066  .Format( rate, bitrate ))
2067  + XO("You may resample to one of the rates below.")
2068  );
2069  }
2070  S.EndHorizontalLay();
2071 
2072  S.StartHorizontalLay(wxALIGN_CENTER, false);
2073  {
2074  choice = S.AddChoice(XXO("Sample Rates"),
2075  [&]{
2076  TranslatableStrings choices;
2077  for (size_t ii = 0, nn = sampRates.size(); ii < nn; ++ii) {
2078  int label = sampRates[ii];
2079  if (label >= lowrate && label <= highrate) {
2080  choices.push_back( Verbatim( "%d" ).Format( label ) );
2081  if (label <= rate)
2082  selected = ii;
2083  }
2084  }
2085  return choices;
2086  }(),
2087  std::max( 0, selected )
2088  );
2089  }
2090  S.EndHorizontalLay();
2091  }
2092  S.EndStatic();
2093 
2094  S.AddStandardButtons();
2095  }
2096  S.EndVerticalLay();
2097 
2098  d.Layout();
2099  d.Fit();
2100  d.SetMinSize(d.GetSize());
2101  d.Center();
2102 
2103  if (d.ShowModal() == wxID_CANCEL) {
2104  return 0;
2105  }
2106 
2107  return wxAtoi(choice->GetStringSelection());
2108 }
2109 
2110 #ifdef USE_LIBID3TAG
2111 struct id3_tag_deleter {
2112  void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
2113 };
2114 using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
2115 #endif
2116 
2117 // returns buffer len; caller frees
2118 unsigned long ExportMP3::AddTags(AudacityProject *WXUNUSED(project), ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags)
2119 {
2120 #ifdef USE_LIBID3TAG
2121  id3_tag_holder tp { id3_tag_new() };
2122 
2123  for (const auto &pair : tags->GetRange()) {
2124  const auto &n = pair.first;
2125  const auto &v = pair.second;
2126  const char *name = "TXXX";
2127 
2128  if (n.CmpNoCase(TAG_TITLE) == 0) {
2129  name = ID3_FRAME_TITLE;
2130  }
2131  else if (n.CmpNoCase(TAG_ARTIST) == 0) {
2132  name = ID3_FRAME_ARTIST;
2133  }
2134  else if (n.CmpNoCase(TAG_ALBUM) == 0) {
2135  name = ID3_FRAME_ALBUM;
2136  }
2137  else if (n.CmpNoCase(TAG_YEAR) == 0) {
2138  // LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
2139  // so we add old one as well.
2140  AddFrame(tp.get(), n, v, "TYER");
2141  name = ID3_FRAME_YEAR;
2142  }
2143  else if (n.CmpNoCase(TAG_GENRE) == 0) {
2144  name = ID3_FRAME_GENRE;
2145  }
2146  else if (n.CmpNoCase(TAG_COMMENTS) == 0) {
2147  name = ID3_FRAME_COMMENT;
2148  }
2149  else if (n.CmpNoCase(TAG_TRACK) == 0) {
2150  name = ID3_FRAME_TRACK;
2151  }
2152 
2153  AddFrame(tp.get(), n, v, name);
2154  }
2155 
2156  tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
2157 
2158  // If this version of libid3tag supports it, use v2.3 ID3
2159  // tags instead of the newer, but less well supported, v2.4
2160  // that libid3tag uses by default.
2161  #ifdef ID3_TAG_HAS_TAG_OPTION_ID3V2_3
2162  tp->options |= ID3_TAG_OPTION_ID3V2_3;
2163  #endif
2164 
2165  *endOfFile = false;
2166 
2167  unsigned long len;
2168 
2169  len = id3_tag_render(tp.get(), 0);
2170  buffer.reinit(len);
2171  len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
2172 
2173  return len;
2174 #else //ifdef USE_LIBID3TAG
2175  return 0;
2176 #endif
2177 }
2178 
2179 #ifdef USE_LIBID3TAG
2180 void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name)
2181 {
2182  struct id3_frame *frame = id3_frame_new(name);
2183 
2184  if (!n.IsAscii() || !v.IsAscii()) {
2185  id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16);
2186  }
2187  else {
2188  id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
2189  }
2190 
2192  id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
2193 
2194  if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
2195  // A hack to get around iTunes not recognizing the comment. The
2196  // language defaults to XXX and, since it's not a valid language,
2197  // iTunes just ignores the tag. So, either set it to a valid language
2198  // (which one???) or just clear it. Unfortunately, there's no supported
2199  // way of clearing the field, so do it directly.
2200  struct id3_frame *frame2 = id3_frame_new(name);
2201  id3_field_setfullstring(id3_frame_field(frame2, 3), ucs4.get());
2202  id3_field *f2 = id3_frame_field(frame2, 1);
2203  memset(f2->immediate.value, 0, sizeof(f2->immediate.value));
2204  id3_tag_attachframe(tp, frame2);
2205  // Now install a second frame with the standard default language = "XXX"
2206  id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
2207  }
2208  else if (strcmp(name, "TXXX") == 0) {
2209  id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
2210 
2211  ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
2212 
2213  id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
2214  }
2215  else {
2216  auto addr = ucs4.get();
2217  id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
2218  }
2219 
2220  id3_tag_attachframe(tp, frame);
2221 }
2222 #endif
2223 
2225  []{ return std::make_unique< ExportMP3 >(); }
2226 };
2227 
2228 //----------------------------------------------------------------------------
2229 // Return library version
2230 //----------------------------------------------------------------------------
2231 
2232 TranslatableString GetMP3Version(wxWindow *parent, bool prompt)
2233 {
2234  MP3Exporter exporter;
2235  auto versionString = XO("MP3 export library not found");
2236 
2237 #ifndef DISABLE_DYNAMIC_LOADING_LAME
2238  if (prompt) {
2239  exporter.FindLibrary(parent);
2240  }
2241 
2242  if (exporter.LoadLibrary(parent, prompt ? MP3Exporter::Yes : MP3Exporter::No)) {
2243 #endif // DISABLE_DYNAMIC_LOADING_LAME
2244  versionString = Verbatim( exporter.GetLibraryVersion() );
2245 #ifdef MP3_EXPORT_BUILT_IN
2246  versionString.Join( XO("(Built-in)"), " " );
2247 #endif
2248 
2249 #ifndef DISABLE_DYNAMIC_LOADING_LAME
2250  }
2251 #endif // DISABLE_DYNAMIC_LOADING_LAME
2252 
2253  return versionString;
2254 }
2255 
get_lame_version_t
const char * get_lame_version_t(void)
Definition: ExportMP3.cpp:717
ExportMP3Options::mJoint
wxRadioButton * mJoint
Definition: ExportMP3.cpp:247
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
MP3Exporter::SetQuality
void SetQuality(int q)
Definition: ExportMP3.cpp:1075
ShuttleGuiBase::StartRadioButtonGroup
void StartRadioButtonGroup(const ChoiceSetting &Setting)
Call this before any TieRadioButton calls.
Definition: ShuttleGui.cpp:1569
MP3Exporter::lame_set_mode
lame_set_mode_t * lame_set_mode
Definition: ExportMP3.cpp:895
MP3Exporter::mQuality
int mQuality
Definition: ExportMP3.cpp:873
TranslatableString
Definition: Types.h:290
lame_set_preset_t
int lame_set_preset_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:750
MP3Exporter::InitLibraryInternal
bool InitLibraryInternal()
Definition: ExportMP3.cpp:1091
lame_init_t
lame_global_flags * lame_init_t(void)
Definition: ExportMP3.cpp:715
FindDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: ExportMP3.cpp:606
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:36
ShuttleGuiBase::AddChoice
wxChoice * AddChoice(const TranslatableString &Prompt, const TranslatableStrings &choices, int Selected=-1)
Definition: ShuttleGui.cpp:391
ShuttleGuiBase::EndRadioButtonGroup
void EndRadioButtonGroup()
Definition: ShuttleGui.cpp:1586
lame_set_error_protection_t
int lame_set_error_protection_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:751
MP3Exporter::GetOutBufferSize
int GetOutBufferSize()
Definition: ExportMP3.cpp:1387
lame_set_num_channels_t
int lame_set_num_channels_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:743
MP3Exporter::SetChannel
void SetChannel(int mode)
Definition: ExportMP3.cpp:1081
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1177
MP3Exporter::lame_set_out_samplerate
lame_set_out_samplerate_t * lame_set_out_samplerate
Definition: ExportMP3.cpp:888
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:302
ExportMP3Options::OnSET
void OnSET(wxCommandEvent &evt)
Definition: ExportMP3.cpp:497
sRegisteredPlugin
static Exporter::RegisteredExportPlugin sRegisteredPlugin
Definition: ExportMP3.cpp:2224
make_iterator_range
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:625
MP3Exporter::lame_encode_buffer_ieee_float
lame_encode_buffer_ieee_float_t * lame_encode_buffer_ieee_float
Definition: ExportMP3.cpp:881
ID_VBR
#define ID_VBR
Definition: ExportMP3.cpp:218
MP3Exporter::~MP3Exporter
~MP3Exporter()
Definition: ExportMP3.cpp:953
MP3Exporter::lame_lib
wxDynamicLibrary lame_lib
Definition: ExportMP3.cpp:862
MP3Exporter::LoadLibrary
bool LoadLibrary(wxWindow *parent, AskUser askuser)
Definition: ExportMP3.cpp:995
fn
static const auto fn
Definition: WaveformView.cpp:1102
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
MP3Exporter::AskUser
AskUser
Definition: ExportMP3.cpp:802
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:274
lame_mp3_tags_fid_t
void lame_mp3_tags_fid_t(lame_global_flags *, FILE *)
Definition: ExportMP3.cpp:755
lame_encode_buffer_interleaved_ieee_float_t
int CDECL lame_encode_buffer_interleaved_ieee_float_t(lame_t gfp, const float pcm[], const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
Definition: ExportMP3.cpp:727
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:67
fixRateNames
static const TranslatableStrings fixRateNames
Definition: ExportMP3.cpp:129
ExportMP3Options::mVBR
wxRadioButton * mVBR
Definition: ExportMP3.cpp:250
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
lame_set_VBR_q_t
int lame_set_VBR_q_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:747
ExportPlugin::AddExtension
void AddExtension(const FileExtension &extension, int index)
Definition: Export.cpp:126
ShowExportErrorDialog
void ShowExportErrorDialog(wxString ErrorCode, TranslatableString message, const TranslatableString &caption)
Definition: Export.cpp:1518
MP3Exporter::ValidLibraryLoaded
bool ValidLibraryLoaded()
Definition: ExportMP3.cpp:1058
MP3Exporter::EncodeBuffer
int EncodeBuffer(float inbuffer[], unsigned char outbuffer[])
Definition: ExportMP3.cpp:1395
anonymous_namespace{ExportMP3.cpp}::ValidateIndex
int ValidateIndex(const std::vector< int > &values, int value, int defaultIndex)
Definition: ExportMP3.cpp:486
wxPanelWrapper
Definition: wxPanelWrapper.h:41
Tags
ID3 Tags (for MP3)
Definition: Tags.h:74
MP3Exporter::lame_set_VBR
lame_set_VBR_t * lame_set_VBR
Definition: ExportMP3.cpp:892
Format
Abstract base class used in importing a file.
TAG_TRACK
#define TAG_TRACK
Definition: Tags.h:63
Tags::GetRange
Iterators GetRange() const
Definition: Tags.cpp:480
MP3Exporter::InitLibraryExternal
bool InitLibraryExternal(wxString libpath)
Definition: ExportMP3.cpp:1143
lame_set_bWriteVbrTag_t
int lame_set_bWriteVbrTag_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:753
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:112
MP3Exporter::FreeLibrary
void FreeLibrary()
Definition: ExportMP3.cpp:1260
GetMP3Version
TranslatableString GetMP3Version(wxWindow *parent, bool prompt)
Definition: ExportMP3.cpp:2232
MP3Exporter::mSamplesPerChunk
static const int mSamplesPerChunk
Definition: ExportMP3.cpp:910
lame_set_brate_t
int lame_set_brate_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:745
MallocString
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:349
XO
#define XO(s)
Definition: Internat.h:32
ProgressResult::Cancelled
@ Cancelled
MP3Exporter::GetLibraryTypes
FileNames::FileTypes GetLibraryTypes()
Definition: ExportMP3.cpp:1586
MP3Exporter::lame_set_num_channels
lame_set_num_channels_t * lame_set_num_channels
Definition: ExportMP3.cpp:889
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:39
OSOUTPUT
#define OSOUTPUT(X)
Definition: FileNames.h:257
lame_global_flags
struct with zillion of control parameters that control lame export (MP3 Conversion DLL).
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1212
MP3Exporter::PutInfoTag
bool PutInfoTag(wxFFile &f, wxFileOffset off)
Definition: ExportMP3.cpp:1463
floatSample
@ floatSample
Definition: Types.h:722
MP3Exporter::lame_init_params
lame_init_params_t * lame_init_params
Definition: ExportMP3.cpp:880
lame_set_quality_t
int lame_set_quality_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:744
fixRateValues
static const std::vector< int > fixRateValues
Definition: ExportMP3.cpp:150
FindDialog::FindDialog
FindDialog(wxWindow *parent, wxString path, wxString name, FileNames::FileTypes types)
Definition: ExportMP3.cpp:588
ExportMP3::CheckFileName
bool CheckFileName(wxFileName &filename, int format) override
Definition: ExportMP3.cpp:1733
FileNames::AllFiles
AUDACITY_DLL_API const FileType AllFiles
Definition: FileNames.h:74
MP3Exporter::mLibIsExternal
bool mLibIsExternal
Definition: ExportMP3.cpp:858
MP3Exporter::mLibPath
wxString mLibPath
Definition: ExportMP3.cpp:861
ShuttleGuiBase::StartPanel
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:983
MP3Exporter::mOutBufferSize
static const int mOutBufferSize
Definition: ExportMP3.cpp:913
ShuttleGuiBase::EndPanel
void EndPanel()
Definition: ShuttleGui.cpp:1011
ID_BROWSE
#define ID_BROWSE
Definition: ExportMP3.cpp:579
ExportMP3
Definition: ExportMP3.cpp:1692
MP3Exporter::InitLibrary
bool InitLibrary(wxString libpath)
Definition: ExportMP3.cpp:1086
ExportMP3Options::LoadNames
void LoadNames(const TranslatableStrings &choices)
Definition: ExportMP3.cpp:568
sampRates
static const std::vector< int > sampRates
Definition: ExportMP3.cpp:205
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterface.h:60
FindDialog::mLibPath
wxFileName mLibPath
Definition: ExportMP3.cpp:690
Tags::Get
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:236
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2248
lame_close_t
int lame_close_t(lame_global_flags *)
Definition: ExportMP3.cpp:739
MP3Exporter
Class used to export MP3 files.
Definition: ExportMP3.cpp:799
ExportMP3::Export
ProgressResult Export(AudacityProject *project, std::unique_ptr< ProgressDialog > &pDialog, unsigned channels, const wxFileNameWrapper &fName, bool selectedOnly, double t0, double t1, MixerSpec *mixerSpec=NULL, const Tags *metadata=NULL, int subformat=0) override
called to export audio into a file.
Definition: ExportMP3.cpp:1759
varRateNames
static const TranslatableStrings varRateNames
Definition: ExportMP3.cpp:171
ExportMP3Options::mMono
wxCheckBox * mMono
Definition: ExportMP3.cpp:248
MP3Exporter::lame_encode_buffer_interleaved_ieee_float
lame_encode_buffer_interleaved_ieee_float_t * lame_encode_buffer_interleaved_ieee_float
Definition: ExportMP3.cpp:882
PRESET_STANDARD
@ PRESET_STANDARD
Definition: ExportMP3.cpp:122
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: Types.h:555
MODE_CBR
@ MODE_CBR
Definition: ExportMP3.h:22
MP3Exporter::mLibraryLoaded
bool mLibraryLoaded
Definition: ExportMP3.cpp:863
lame_init_params_t
int lame_init_params_t(lame_global_flags *)
Definition: ExportMP3.cpp:716
ID_DLOAD
#define ID_DLOAD
Definition: ExportMP3.cpp:580
ExportMP3::SetNumExportChannels
int SetNumExportChannels() override
Exporter plug-ins may override this to specify the number of channels in exported file....
Definition: ExportMP3.cpp:1750
FindDialog::mPath
wxString mPath
Definition: ExportMP3.cpp:692
lame_encode_flush_t
int lame_encode_flush_t(lame_global_flags *gf, unsigned char *mp3buf, int size)
Definition: ExportMP3.cpp:734
MP3Exporter::GetLibraryName
wxString GetLibraryName()
Definition: ExportMP3.cpp:1581
ShowDiskFullExportErrorDialog
void ShowDiskFullExportErrorDialog(const wxFileNameWrapper &fileName)
Definition: Export.cpp:1529
XXO
#define XXO(s)
Definition: Internat.h:45
MP3Exporter::lame_set_in_samplerate
lame_set_in_samplerate_t * lame_set_in_samplerate
Definition: ExportMP3.cpp:887
MP3Exporter::mEncoding
bool mEncoding
Definition: ExportMP3.cpp:870
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1170
ExportMP3Options::mCBR
wxRadioButton * mCBR
Definition: ExportMP3.cpp:252
ExportPlugin::InitProgress
static void InitProgress(std::unique_ptr< ProgressDialog > &pDialog, const TranslatableString &title, const TranslatableString &message)
Definition: Export.cpp:250
ProgressResult
ProgressResult
Definition: ProgressDialog.h:33
lame_get_lametag_frame_t
size_t lame_get_lametag_frame_t(const lame_global_flags *, unsigned char *buffer, size_t size)
Definition: ExportMP3.cpp:754
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1160
ProgressResult::Success
@ Success
MP3Exporter::mInfoTagLen
size_t mInfoTagLen
Definition: ExportMP3.cpp:918
lame_encode_buffer_ieee_float_t
int CDECL lame_encode_buffer_ieee_float_t(lame_t gfp, const float pcm_l[], const float pcm_r[], const int nsamples, unsigned char *mp3buf, const int mp3buf_size)
Definition: ExportMP3.cpp:719
ShuttleGuiBase::AddTextBox
wxTextCtrl * AddTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:631
ShuttleGui::Disable
ShuttleGui & Disable(bool disabled=true)
Definition: ShuttleGui.h:657
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1203
ExportPlugin::SetFormat
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:116
FindDialog::mPathText
wxTextCtrl * mPathText
Definition: ExportMP3.cpp:697
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1196
FileNames::PathFromAddr
AUDACITY_DLL_API FilePath PathFromAddr(void *addr)
lame_set_disable_reservoir_t
int lame_set_disable_reservoir_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:752
CHANNEL_MONO
@ CHANNEL_MONO
Definition: ExportMP3.cpp:111
MP3Exporter::GetLibraryPath
wxString GetLibraryPath()
WXMAC
Definition: ExportMP3.cpp:1576
ExportMP3::AskResample
int AskResample(int bitrate, int rate, int lowrate, int highrate)
Definition: ExportMP3.cpp:2043
MP3Exporter::mInfoTagBuf
unsigned char mInfoTagBuf[2880]
Definition: ExportMP3.cpp:917
ID_SET
#define ID_SET
Definition: ExportMP3.cpp:217
MP3Exporter::lame_set_disable_reservoir
lame_set_disable_reservoir_t * lame_set_disable_reservoir
Definition: ExportMP3.cpp:898
name
const TranslatableString name
Definition: Distortion.cpp:98
MP3Exporter::SetMode
void SetMode(int mode)
Definition: ExportMP3.cpp:1065
ProgressResult::Stopped
@ Stopped
MP3Exporter::lame_set_brate
lame_set_brate_t * lame_set_brate
Definition: ExportMP3.cpp:891
TAG_GENRE
#define TAG_GENRE
Definition: Tags.h:65
ShuttleGuiBase::StartTwoColumn
void StartTwoColumn()
Definition: ShuttleGui.h:374
format
int format
Definition: ExportPCM.cpp:54
MP3Exporter::lame_set_bWriteVbrTag
lame_set_bWriteVbrTag_t * lame_set_bWriteVbrTag
Definition: ExportMP3.cpp:899
lame_set_VBR_min_bitrate_kbps_t
int lame_set_VBR_min_bitrate_kbps_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:748
ExportMP3Options::mAbrRate
long mAbrRate
Definition: ExportMP3.cpp:258
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:503
MODE_VBR
@ MODE_VBR
Definition: ExportMP3.h:20
anonymous_namespace{ExportMP3.cpp}::ValidateValue
int ValidateValue(const std::vector< int > &values, int value, int defaultValue)
Definition: ExportMP3.cpp:479
Export.h
TAG_YEAR
#define TAG_YEAR
Definition: Tags.h:64
ExportPlugin::SetDescription
void SetDescription(const TranslatableString &description, int index)
Definition: Export.cpp:121
MP3Exporter::EncodeRemainder
int EncodeRemainder(float inbuffer[], int nSamples, unsigned char outbuffer[])
Definition: ExportMP3.cpp:1405
ExportMP3Options::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: ExportMP3.cpp:328
FindDialog::mTypes
FileNames::FileTypes mTypes
Definition: ExportMP3.cpp:694
wxDialogWrapper::SetName
void SetName(const TranslatableString &title)
Definition: wxPanelWrapper.cpp:76
MP3Exporter::lame_set_VBR_min_bitrate_kbps
lame_set_VBR_min_bitrate_kbps_t * lame_set_VBR_min_bitrate_kbps
Definition: ExportMP3.cpp:894
MP3Exporter::InitializeStream
int InitializeStream(unsigned channels, int sampleRate)
Definition: ExportMP3.cpp:1285
MP3ChannelModeSetting
static EnumSetting< MP3ChannelMode > MP3ChannelModeSetting
Definition: ExportMP3.cpp:311
MP3Exporter::lame_set_preset
lame_set_preset_t * lame_set_preset
Definition: ExportMP3.cpp:896
ExportMP3Options::TransferDataToWindow
bool TransferDataToWindow() override
Definition: ExportMP3.cpp:453
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:353
ID_ABR
#define ID_ABR
Definition: ExportMP3.cpp:219
MP3Exporter::FindLibrary
bool FindLibrary(wxWindow *parent)
Definition: ExportMP3.cpp:960
CHANNEL_STEREO
@ CHANNEL_STEREO
Definition: ExportMP3.cpp:110
ExportMP3Options::OnVBR
void OnVBR(wxCommandEvent &evt)
Definition: ExportMP3.cpp:508
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:886
ExportPlugin::SetMaxChannels
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:141
eIsSavingToPrefs
@ eIsSavingToPrefs
Definition: ShuttleGui.h:46
ID_MONO
#define ID_MONO
Definition: ExportMP3.cpp:222
wxDialogWrapper
Definition: wxPanelWrapper.h:81
Exporter::RegisteredExportPlugin
Definition: Export.h:176
MP3Exporter::EncodeBufferMono
int EncodeBufferMono(float inbuffer[], unsigned char outbuffer[])
Definition: ExportMP3.cpp:1416
FindDialog
Definition: ExportMP3.cpp:583
ExportMP3Options::OnMono
void OnMono(wxCommandEvent &evt)
Definition: ExportMP3.cpp:557
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow)
Definition: ShuttleGui.cpp:292
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:151
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const wxString &localFileName, const wxString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:238
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
FindDialog::mName
wxString mName
Definition: ExportMP3.cpp:693
FileNames::SelectFile
AUDACITY_DLL_API FilePath SelectFile(Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
ExportMP3Options::mRate
wxChoice * mRate
Definition: ExportMP3.cpp:253
ID_QUALITY
#define ID_QUALITY
Definition: ExportMP3.cpp:221
ExportMP3Options::mVbrRate
long mVbrRate
Definition: ExportMP3.cpp:257
FileNames::DynamicLibraries
AUDACITY_DLL_API const FileType DynamicLibraries
Definition: FileNames.h:76
MP3Exporter::get_lame_version
get_lame_version_t * get_lame_version
Definition: ExportMP3.cpp:885
names
static TranslatableStrings names
Definition: Tags.cpp:743
_
#define _(s)
Definition: Internat.h:76
MP3Exporter::lame_init
lame_init_t * lame_init
Definition: ExportMP3.cpp:879
setRateNamesShort
static const TranslatableStrings setRateNamesShort
Definition: ExportMP3.cpp:197
ExportMP3Options::OnQuality
void OnQuality(wxCommandEvent &evt)
Definition: ExportMP3.cpp:539
MODE_ABR
@ MODE_ABR
Definition: ExportMP3.h:21
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
MP3Exporter::CancelEncoding
void CancelEncoding()
Definition: ExportMP3.cpp:1458
ExportMP3Options::OnABR
void OnABR(wxCommandEvent &evt)
Definition: ExportMP3.cpp:519
ExportPlugin::CreateMixer
std::unique_ptr< Mixer > CreateMixer(const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerSpec *mixerSpec)
Definition: Export.cpp:222
ProjectSettings::GetRate
double GetRate() const
Definition: ProjectSettings.cpp:166
Verbatim
TranslatableString Verbatim(wxString str)
Definition: Types.h:581
MP3Exporter::mGF
lame_global_flags * mGF
Definition: ExportMP3.cpp:908
MP3ChannelMode
MP3ChannelMode
Definition: ExportMP3.cpp:108
ExportPlugin::SetCanMetaData
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:146
ExportMP3Options::~ExportMP3Options
virtual ~ExportMP3Options()
Definition: ExportMP3.cpp:289
n_kbps
TranslatableString n_kbps(int n)
Definition: ExportMP3.cpp:127
FindDialog::GetLibPath
wxString GetLibPath()
Definition: ExportMP3.cpp:680
setRateNames
static const TranslatableStrings setRateNames
Definition: ExportMP3.cpp:189
ExportMP3Options::ExportMP3Options
ExportMP3Options(wxWindow *parent, int format)
Definition: ExportMP3.cpp:275
ProjectWindow::Find
static ProjectWindow * Find(AudacityProject *pProject)
Definition: ProjectWindow.cpp:541
QUALITY_2
@ QUALITY_2
Definition: ExportMP3.cpp:115
MP3Exporter::FinishStream
int FinishStream(unsigned char outbuffer[])
Definition: ExportMP3.cpp:1437
PRESET_INSANE
@ PRESET_INSANE
Definition: ExportMP3.cpp:120
TAG_COMMENTS
#define TAG_COMMENTS
Definition: Tags.h:66
FindDialog::OnBrowse
void OnBrowse(wxCommandEvent &WXUNUSED(event))
Definition: ExportMP3.cpp:654
FindDialog::OnDownload
void OnDownload(wxCommandEvent &WXUNUSED(event))
Definition: ExportMP3.cpp:675
ShuttleGuiBase::TieNumberAsChoice
virtual wxChoice * TieNumberAsChoice(const TranslatableString &Prompt, const SettingSpec< int > &Setting, const TranslatableStrings &Choices, const std::vector< int > *pInternalChoices=nullptr, int iNoMatchSelector=0)
Definition: ShuttleGui.cpp:1985
lame_set_VBR_t
int lame_set_VBR_t(lame_global_flags *, vbr_mode)
Definition: ExportMP3.cpp:746
MP3Exporter::lame_encode_flush
lame_encode_flush_t * lame_encode_flush
Definition: ExportMP3.cpp:883
TAG_ARTIST
#define TAG_ARTIST
Definition: Tags.h:61
lame_set_out_samplerate_t
int lame_set_out_samplerate_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:742
EnumSetting
Adapts EnumSettingBase to a particular enumeration type.
Definition: Prefs.h:174
ExportMP3::AddTags
unsigned long AddTags(AudacityProject *project, ArrayOf< char > &buffer, bool *endOfFile, const Tags *tags)
Definition: ExportMP3.cpp:2118
ExportPlugin::AddFormat
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:100
MP3Exporter::mBitrate
int mBitrate
Definition: ExportMP3.cpp:872
MP3RateModeSetting
EnumSetting< MP3RateMode > MP3RateModeSetting
Definition: ExportMP3.cpp:294
ExportMP3.h
MP3Exporter::GetLibraryVersion
wxString GetLibraryVersion()
Definition: ExportMP3.cpp:1274
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2406
MP3Exporter::lame_set_quality
lame_set_quality_t * lame_set_quality
Definition: ExportMP3.cpp:890
MP3Exporter::lame_mp3_tags_fid
lame_mp3_tags_fid_t * lame_mp3_tags_fid
Definition: ExportMP3.cpp:901
ExportMP3Options::OnCBR
void OnCBR(wxCommandEvent &evt)
Definition: ExportMP3.cpp:530
MP3Exporter::EncodeRemainderMono
int EncodeRemainderMono(float inbuffer[], int nSamples, unsigned char outbuffer[])
Definition: ExportMP3.cpp:1426
ShuttleGuiBase::TieRadioButton
wxRadioButton * TieRadioButton()
This function must be within a StartRadioButtonGroup - EndRadioButtonGroup pair.
Definition: ShuttleGui.cpp:1510
FileNames::FileTypes
std::vector< FileType > FileTypes
Definition: FileNames.h:79
MP3Exporter::lame_get_lametag_frame
lame_get_lametag_frame_t * lame_get_lametag_frame
Definition: ExportMP3.cpp:900
MP3Exporter::Yes
@ Yes
Definition: ExportMP3.cpp:805
MP3Exporter::lame_set_VBR_q
lame_set_VBR_q_t * lame_set_VBR_q
Definition: ExportMP3.cpp:893
MP3Exporter::SetBitrate
void SetBitrate(int rate)
Definition: ExportMP3.cpp:1070
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:231
TranslatableString::Translation
wxString Translation() const
Definition: Types.h:337
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:497
wxDialogWrapper::SetName
void SetName()
Definition: wxPanelWrapper.cpp:81
ShuttleGuiBase::EndTwoColumn
void EndTwoColumn()
Definition: ShuttleGui.h:375
MixerSpec
Class used with Mixer.
Definition: Mix.h:57
eIsCreatingFromPrefs
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:45
MP3Exporter::mMode
int mMode
Definition: ExportMP3.cpp:871
ExportMP3Options::mCbrRate
long mCbrRate
Definition: ExportMP3.cpp:259
ExportPlugin
Definition: Export.h:65
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:456
ExportMP3Options::mSetRate
long mSetRate
Definition: ExportMP3.cpp:256
MP3Exporter::Maybe
@ Maybe
Definition: ExportMP3.cpp:804
MP3Exporter::lame_set_error_protection
lame_set_error_protection_t * lame_set_error_protection
Definition: ExportMP3.cpp:897
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:915
safenew
#define safenew
Definition: MemoryX.h:8
ID_CBR
#define ID_CBR
Definition: ExportMP3.cpp:220
lrint
#define lrint(dbl)
Definition: float_cast.h:148
values
const wxChar * values
Definition: Equalization.cpp:471
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:195
MODE_SET
@ MODE_SET
Definition: ExportMP3.h:19
ExportMP3Options::mStereo
wxRadioButton * mStereo
Definition: ExportMP3.cpp:246
MP3Exporter::lame_close
lame_close_t * lame_close
Definition: ExportMP3.cpp:884
anonymous_namespace{CompareAudioCommand.cpp}::reg
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
Definition: CompareAudioCommand.cpp:41
ExportMP3Options::TransferDataFromWindow
bool TransferDataFromWindow() override
Definition: ExportMP3.cpp:458
CHANNEL_JOINT
@ CHANNEL_JOINT
Definition: ExportMP3.cpp:109
END_EVENT_TABLE
END_EVENT_TABLE()
ArrayOf< char >
ExportMP3Options::mSET
wxRadioButton * mSET
Definition: ExportMP3.cpp:249
lame_set_mode_t
int lame_set_mode_t(lame_global_flags *, MPEG_mode)
Definition: ExportMP3.cpp:749
FileNames::FileType
Definition: FileNames.h:55
PRESET_MEDIUM
@ PRESET_MEDIUM
Definition: ExportMP3.cpp:123
ExportMP3::OptionsCreate
void OptionsCreate(ShuttleGui &S, int format) override
Definition: ExportMP3.cpp:2038
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
PRESET_EXTREME
@ PRESET_EXTREME
Definition: ExportMP3.cpp:121
ExportMP3Options
Definition: ExportMP3.cpp:225
ExportMP3Options::mABR
wxRadioButton * mABR
Definition: ExportMP3.cpp:251
MP3Exporter::mChannel
int mChannel
Definition: ExportMP3.cpp:875
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:638
lame_set_in_samplerate_t
int lame_set_in_samplerate_t(lame_global_flags *, int)
Definition: ExportMP3.cpp:741
ExportMP3::ExportMP3
ExportMP3()
Definition: ExportMP3.cpp:1722
MP3Exporter::No
@ No
Definition: ExportMP3.cpp:803
MP3Exporter::MP3Exporter
MP3Exporter()
Definition: ExportMP3.cpp:921
TAG_ALBUM
#define TAG_ALBUM
Definition: Tags.h:62