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