1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-31 07:59:27 +02:00

Eliminate an overload of TieChoice...

... with one exception (/FileFormats/FFmpegAACProfile),
the calls are replaced with TieNumberAsChoice.

Some unfortunately repetitious string tables are a small price in exchange for
reduced confusion in ShuttleGui.cpp

Untranslated strings are passed to TieNumberAsChoice, which is wrong, but that
will be made right in the next commit when we change the implementation of that
function
This commit is contained in:
Paul Licameli 2019-02-23 15:13:46 -05:00
parent dc3e872ca6
commit 5638d6844f
7 changed files with 359 additions and 471 deletions

View File

@ -1679,30 +1679,6 @@ wxString ShuttleGuiBase::TranslateFromIndex( const int nIn, const wxArrayStringE
return wxT("");
}
/// Int-to-Index (choices can be items like e.g 0x400120 )
int ShuttleGuiBase::TranslateToIndex( const int Value, const std::vector<int> &Choices )
{
int n = make_iterator_range(Choices).index( Value );
if( n == wxNOT_FOUND )
n=miNoMatchSelector;
miNoMatchSelector = 0;
return n;
}
/// Index-to-int (choices can be items like e.g 0x400120 )
int ShuttleGuiBase::TranslateFromIndex( const int nIn, const std::vector<int> &Choices )
{
int n = nIn;
if( n== wxNOT_FOUND )
n=miNoMatchSelector;
miNoMatchSelector = 0;
if( n < (int)Choices.size() )
{
return Choices[n];
}
return 0;
}
//-----------------------------------------------------------------------//
@ -1938,37 +1914,6 @@ wxChoice * ShuttleGuiBase::TieChoice(
return pChoice;
}
/// Variant of the standard TieChoice which does the two step exchange
/// between gui and stack variable and stack variable and shuttle.
/// Difference to previous one is that the Translated choices and default
/// are integers, not Strings.
/// @param Prompt The prompt shown beside the control.
/// @param SettingName The setting name as stored in gPrefs
/// @param Default The default value for this control (translated)
/// @param Choices An array of choices that appear on screen.
/// @param InternalChoices The corresponding values (as an integer array)
wxChoice * ShuttleGuiBase::TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayStringEx & Choices,
const std::vector<int> & InternalChoices)
{
wxChoice * pChoice=(wxChoice*)NULL;
int TempIndex=0;
int TranslatedInt = Default;
WrappedType WrappedRef( TranslatedInt );
// Get from prefs does 1 and 2.
// Put to prefs does 2 and 3.
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Int from Prefs.
if( DoStep(1) ) TempIndex = TranslateToIndex( TranslatedInt, InternalChoices ); // Int to an index.
if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, Choices ); // Get/Put index from GUI.
if( DoStep(3) ) TranslatedInt = TranslateFromIndex( TempIndex, InternalChoices ); // Index to int
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs.
return pChoice;
}
/// Variant of the standard TieChoice which does the two step exchange
/// between gui and stack variable and stack variable and shuttle.
/// The Translated choices and default are integers, not Strings.

View File

@ -183,8 +183,6 @@ public:
bool DoStep( int iStep );
int TranslateToIndex( const wxString &Value, const wxArrayStringEx &Choices );
wxString TranslateFromIndex( const int nIn, const wxArrayStringEx &Choices );
int TranslateToIndex( const int Value, const std::vector<int> &Choices );
int TranslateFromIndex( const int nIn, const std::vector<int> &Choices );
//-- Tie functions both add controls and also read/write to them.
// The ones taking a 'WrappedType' are type-generic and are used by the type specific ones.
@ -246,15 +244,6 @@ public:
const wxArrayStringEx &Choices,
const wxArrayStringEx & InternalChoices );
// This overload of TieChoice should no longer be used in Preferences!
// Some uses do remain in export settings dialogs.
virtual wxChoice * TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayStringEx & Choices,
const std::vector<int> & InternalChoices );
// This overload presents what is really a numerical setting as a choice among
// commonly used values, but the choice is not necessarily exhaustive.
// This behaves just like the previous for building dialogs, but the

View File

@ -213,14 +213,6 @@ public:
const wxArrayStringEx &Choices,
const wxArrayStringEx & InternalChoices ) override;
// An assertion will be violated if this override is reached!
wxChoice * TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayStringEx & Choices,
const std::vector<int> & InternalChoices) override;
wxChoice * TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,
@ -310,34 +302,6 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
EndStruct();
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
}
wxChoice * ShuttleGuiGetDefinition::TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayStringEx & Choices,
const std::vector<int> & InternalChoices)
{
// Should no longer come here!
// Choice controls in Preferences that really are exhaustive choices among
// non-numerical options must now encode the internal choices as strings,
// not numbers.
wxASSERT(false);
// But if we do get here anyway, proceed sub-optimally as before.
StartStruct();
AddItem( SettingName, "id" );
AddItem( Prompt, "prompt" );
AddItem( "enum", "type" );
AddItem( Default, "default" );
StartField( "enum" );
StartArray();
for( size_t i=0;i<Choices.size(); i++ )
AddItem( Choices[i] );
EndArray();
EndField();
EndStruct();
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
}
wxChoice * ShuttleGuiGetDefinition::TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,

View File

@ -138,20 +138,61 @@ static const wxChar *FFmpegExportCtrlIDNames[] = {
// ExportFFmpegAC3Options Class
//----------------------------------------------------------------------------
// This initialises content for the static const member variables defined in
// ExportFFmpegDialogs.h (note no static keyword - important!)
const int ExportFFmpegAC3Options::iAC3BitRates[] = { 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 448000, 512000, 576000, 640000 };
namespace
{
const wxArrayStringEx AC3BitRateNames{
// i18n-hint kbps abbreviates "thousands of bits per second"
XO("32 kbps"),
XO("40 kbps"),
XO("48 kbps"),
XO("56 kbps"),
XO("64 kbps"),
XO("80 kbps"),
XO("96 kbps"),
XO("112 kbps"),
XO("128 kbps"),
XO("160 kbps"),
XO("192 kbps"),
XO("224 kbps"),
XO("256 kbps"),
XO("320 kbps"),
XO("384 kbps"),
XO("448 kbps"),
XO("512 kbps"),
XO("576 kbps"),
XO("640 kbps"),
};
const std::vector< int > AC3BitRateValues{
32000,
40000,
48000,
56000,
64000,
80000,
96000,
112000,
128000,
160000,
192000,
224000,
256000,
320000,
384000,
448000,
512000,
576000,
640000,
};
}
const int ExportFFmpegAC3Options::iAC3SampleRates[] = { 32000, 44100, 48000, 0 };
ExportFFmpegAC3Options::ExportFFmpegAC3Options(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
for (unsigned int i=0; i < (sizeof(iAC3BitRates)/sizeof(int)); i++)
{
mBitRateNames.push_back(wxString::Format(_("%i kbps"),iAC3BitRates[i]/1000));
mBitRateLabels.push_back(iAC3BitRates[i]);
}
ShuttleGui S(this, eIsCreatingFromPrefs);
PopulateOrExchange(S);
@ -173,8 +214,13 @@ void ExportFFmpegAC3Options::PopulateOrExchange(ShuttleGui & S)
{
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/AC3BitRate"),
160000, mBitRateNames, mBitRateLabels);
S.TieNumberAsChoice(
_("Bit Rate:"),
wxT("/FileFormats/AC3BitRate"),
160000,
AC3BitRateNames,
&AC3BitRateValues
);
}
S.EndMultiColumn();
}
@ -264,20 +310,40 @@ bool ExportFFmpegAACOptions::TransferDataFromWindow()
// ExportFFmpegAMRNBOptions Class
//----------------------------------------------------------------------------
namespace {
/// Bit Rates supported by libAMR-NB encoder
/// Sample Rate is always 8 kHz
int ExportFFmpegAMRNBOptions::iAMRNBBitRate[] =
{ 4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200 };
const wxArrayStringEx AMRNBBitRateNames
{
// i18n-hint kbps abbreviates "thousands of bits per second"
XO("4.75 kbps"),
XO("5.15 kbps"),
XO("5.90 kbps"),
XO("6.70 kbps"),
XO("7.40 kbps"),
XO("7.95 kbps"),
XO("10.20 kbps"),
XO("12.20 kbps"),
};
const std::vector< int > AMRNBBitRateValues
{
4750,
5150,
5900,
6700,
7400,
7950,
10200,
12200,
};
}
ExportFFmpegAMRNBOptions::ExportFFmpegAMRNBOptions(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
for (unsigned int i=0; i < (sizeof(iAMRNBBitRate)/sizeof(int)); i++)
{
mBitRateNames.push_back(wxString::Format(_("%.2f kbps"),(float)iAMRNBBitRate[i]/1000));
mBitRateLabels.push_back(iAMRNBBitRate[i]);
}
ShuttleGui S(this, eIsCreatingFromPrefs);
PopulateOrExchange(S);
@ -299,8 +365,13 @@ void ExportFFmpegAMRNBOptions::PopulateOrExchange(ShuttleGui & S)
{
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/AMRNBBitRate"),
12200, mBitRateNames, mBitRateLabels);
S.TieNumberAsChoice(
_("Bit Rate:"),
wxT("/FileFormats/AMRNBBitRate"),
12200,
AMRNBBitRateNames,
&AMRNBBitRateValues
);
}
S.EndMultiColumn();
}
@ -335,20 +406,46 @@ bool ExportFFmpegAMRNBOptions::TransferDataFromWindow()
const int ExportFFmpegWMAOptions::iWMASampleRates[] =
{ 8000, 11025, 16000, 22050, 44100, 0};
namespace {
/// Bit Rates supported by WMA encoder. Setting bit rate to other values will not result in different file size.
const int ExportFFmpegWMAOptions::iWMABitRate[] =
{ 24000, 32000, 40000, 48000, 64000, 80000, 96000, 128000, 160000, 192000, 256000, 320000 };
const wxArrayStringEx WMABitRateNames
{
// i18n-hint kbps abbreviates "thousands of bits per second"
XO("24 kbps"),
XO("32 kbps"),
XO("40 kbps"),
XO("48 kbps"),
XO("64 kbps"),
XO("80 kbps"),
XO("96 kbps"),
XO("128 kbps"),
XO("160 kbps"),
XO("192 kbps"),
XO("256 kbps"),
XO("320 kbps"),
};
const std::vector< int > WMABitRateValues{
24000,
32000,
40000,
48000,
64000,
80000,
96000,
128000,
160000,
192000,
256000,
320000,
};
}
ExportFFmpegWMAOptions::ExportFFmpegWMAOptions(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
for (unsigned int i=0; i < (sizeof(iWMABitRate)/sizeof(int)); i++)
{
/* i18n-hint: abbreviates thousands of bits per second */
mBitRateNames.push_back(wxString::Format(_("%i kbps"),iWMABitRate[i]/1000));
mBitRateLabels.push_back(iWMABitRate[i]);
}
ShuttleGui S(this, eIsCreatingFromPrefs);
PopulateOrExchange(S);
@ -370,8 +467,13 @@ void ExportFFmpegWMAOptions::PopulateOrExchange(ShuttleGui & S)
{
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/WMABitRate"),
128000, mBitRateNames, mBitRateLabels);
S.TieNumberAsChoice(
_("Bit Rate:"),
wxT("/FileFormats/WMABitRate"),
128000,
WMABitRateNames,
&WMABitRateValues
);
}
S.EndMultiColumn();
}
@ -1215,36 +1317,17 @@ CompatibilityEntry ExportFFmpegOptions::CompatibilityList[] =
};
/// AAC profiles
int ExportFFmpegOptions::iAACProfileValues[] = {
FF_PROFILE_AAC_LOW,
FF_PROFILE_AAC_MAIN,
/*FF_PROFILE_AAC_SSR,*/
FF_PROFILE_AAC_LTP
};
/// Names of AAC profiles to be displayed
static wxString iAACProfileNames(int index)
{
static const wxString names[] = {
XO("LC"),
XO("Main"),
/*_("SSR"),*/ //SSR is not supported
XO("LTP")
};
class NamesArray final : public TranslatableStringArray
// The FF_PROFILE_* enumeration is defined in the ffmpeg library
// PRL: I cant find where this preference is used!
ChoiceSetting AACProfiles { wxT("/FileFormats/FFmpegAACProfile"),
{
void Populate() override
{
for (auto &name : names)
mContents.push_back( wxGetTranslation( name ) );
}
};
static NamesArray theArray;
return theArray.Get()[ index ];
}
{wxT("1") /*FF_PROFILE_AAC_LOW*/, XO("LC")},
{wxT("0") /*FF_PROFILE_AAC_MAIN*/, XO("Main")},
// {wxT("2") /*FF_PROFILE_AAC_SSR*/, XO("SSR")}, //SSR is not supported
{wxT("3") /*FF_PROFILE_AAC_LTP*/, XO("LTP")},
},
0, // "1"
};
/// List of export types
ExposedFormat ExportFFmpegOptions::fmts[] =
@ -1349,30 +1432,18 @@ ApplicableFor ExportFFmpegOptions::apptable[] =
{FALSE,FFmpegExportCtrlID(0),AV_CODEC_ID_NONE,NULL}
};
/// Prediction order method - names. Labels are indices of this array.
static wxString PredictionOrderMethodNames(int index)
{
static const wxString names[] = {
XO("Estimate"),
XO("2-level"),
XO("4-level"),
XO("8-level"),
XO("Full search"),
XO("Log search")
};
namespace {
class NamesArray final : public TranslatableStringArray
{
void Populate() override
{
for (auto &name : names)
mContents.push_back( wxGetTranslation( name ) );
}
};
/// Prediction order method - names.
const wxArrayStringEx PredictionOrderMethodNames {
XO("Estimate"),
XO("2-level"),
XO("4-level"),
XO("8-level"),
XO("Full search"),
XO("Log search"),
};
static NamesArray theArray;
return theArray.Get()[ index ];
}
@ -1399,18 +1470,6 @@ ExportFFmpegOptions::ExportFFmpegOptions(wxWindow *parent)
FetchFormatList();
FetchCodecList();
for (unsigned int i = 0; i < 6; i++)
{
mPredictionOrderMethodLabels.push_back(i);
mPredictionOrderMethodNames.push_back(wxString::Format(wxT("%s"),PredictionOrderMethodNames(i)));
}
for (unsigned int i=0; i < (sizeof(iAACProfileValues)/sizeof(int)); i++)
{
mProfileNames.push_back(wxString::Format(wxT("%s"),iAACProfileNames(i)));
mProfileLabels.push_back(iAACProfileValues[i]);
}
PopulateOrExchange(S);
//Select the format that was selected last time this dialog was closed
@ -1549,8 +1608,8 @@ void ExportFFmpegOptions::PopulateOrExchange(ShuttleGui & S)
mCutoffSpin = S.Id(FECutoffID).TieSpinCtrl(_("Cutoff:"), wxT("/FileFormats/FFmpegCutOff"), 0, 10000000, 0);
mCutoffSpin->SetToolTip(_("Audio cutoff bandwidth (Hz)\nOptional\n0 - automatic"));
mProfileChoice = S.Id(FEProfileID).TieChoice(_("Profile:"), wxT("/FileFormats/FFmpegAACProfile"),
mProfileLabels[0], mProfileNames, mProfileLabels);
mProfileChoice = S.Id(FEProfileID)
.TieChoice(_("Profile:"), AACProfiles);
mProfileChoice->SetSizeHints( 100,-1);
mProfileChoice->SetToolTip(_("AAC Profile\nLow Complexity - default\nMost players won't play anything other than LC"));
@ -1571,8 +1630,13 @@ void ExportFFmpegOptions::PopulateOrExchange(ShuttleGui & S)
mLPCCoeffsPrecisionSpin = S.Id(FELPCCoeffsID).TieSpinCtrl(_("LPC"), wxT("/FileFormats/FFmpegLPCCoefPrec"), 0, 15, 0);
mLPCCoeffsPrecisionSpin->SetToolTip(_("LPC coefficients precision\nOptional\n0 - default\nmin - 1\nmax - 15"));
mPredictionOrderMethodChoice = S.Id(FEPredOrderID).TieChoice(_("PdO Method:"), wxT("/FileFormats/FFmpegPredOrderMethod"),
mPredictionOrderMethodLabels[4], mPredictionOrderMethodNames, mPredictionOrderMethodLabels);
mPredictionOrderMethodChoice = S.Id(FEPredOrderID)
.TieNumberAsChoice(
_("PdO Method:"),
wxT("/FileFormats/FFmpegPredOrderMethod"),
4, // Full search
PredictionOrderMethodNames
);
mPredictionOrderMethodChoice->SetSizeHints( 100,-1);
mPredictionOrderMethodChoice->SetToolTip(_("Prediction Order Method\nEstimate - fastest, lower compression\nLog search - slowest, best compression\nFull search - default"));

View File

@ -81,17 +81,12 @@ public:
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
/// Bit Rates supported by AC3 encoder
static const int iAC3BitRates[];
/// Sample Rates supported by AC3 encoder (must end with zero-element)
/// It is not used in dialog anymore, but will be required later
static const int iAC3SampleRates[];
private:
wxArrayStringEx mBitRateNames;
std::vector<int> mBitRateLabels;
wxChoice *mBitRateChoice;
int mBitRateFromChoice;
};
@ -123,13 +118,8 @@ public:
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
static int iAMRNBBitRate[];
private:
wxArrayStringEx mBitRateNames;
std::vector<int> mBitRateLabels;
wxChoice *mBitRateChoice;
int mBitRateFromChoice;
};
@ -146,13 +136,9 @@ public:
bool TransferDataFromWindow() override;
static const int iWMASampleRates[];
static const int iWMABitRate[];
private:
wxArrayStringEx mBitRateNames;
std::vector<int> mBitRateLabels;
wxChoice *mBitRateChoice;
int mBitRateFromChoice;
};
@ -212,7 +198,6 @@ public:
// Static tables
static CompatibilityEntry CompatibilityList[];
static int iAACProfileValues[];
static ExposedFormat fmts[];
static const int iAACSampleRates[];
static ApplicableFor apptable[];
@ -227,10 +212,6 @@ private:
wxArrayString mFormatLongNames;
wxArrayStringEx mCodecNames;
wxArrayString mCodecLongNames;
wxArrayStringEx mProfileNames;
std::vector<int> mProfileLabels;
wxArrayStringEx mPredictionOrderMethodNames;
std::vector<int> mPredictionOrderMethodLabels;
wxChoice *mFormatChoice;
wxChoice *mCodecChoice;

View File

@ -75,12 +75,51 @@
// ExportMP2Options
//----------------------------------------------------------------------------
static int iBitrates[] = {
16, 24, 32, 40, 48, 56, 64,
80, 96, 112, 128, 160,
192, 224, 256, 320, 384
namespace {
const wxArrayStringEx BitRateNames {
// i18n-hint kbps abbreviates "thousands of bits per second"
XO("16 kbps"),
XO("24 kbps"),
XO("32 kbps"),
XO("40 kbps"),
XO("48 kbps"),
XO("56 kbps"),
XO("64 kbps"),
XO("80 kbps"),
XO("96 kbps"),
XO("112 kbps"),
XO("128 kbps"),
XO("160 kbps"),
XO("192 kbps"),
XO("224 kbps"),
XO("256 kbps"),
XO("320 kbps"),
XO("384 kbps"),
};
const std::vector< int > BitRateValues {
16,
24,
32,
40,
48,
56,
64,
80,
96,
112,
128,
160,
192,
224,
256,
320,
384,
};
}
class ExportMP2Options final : public wxPanelWrapper
{
public:
@ -90,10 +129,6 @@ public:
void PopulateOrExchange(ShuttleGui & S);
bool TransferDataToWindow() override;
bool TransferDataFromWindow() override;
private:
wxArrayStringEx mBitRateNames;
std::vector<int> mBitRateLabels;
};
///
@ -101,12 +136,6 @@ private:
ExportMP2Options::ExportMP2Options(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
for (unsigned int i=0; i < (sizeof(iBitrates)/sizeof(int)); i++)
{
mBitRateNames.push_back(wxString::Format(_("%i kbps"),iBitrates[i]));
mBitRateLabels.push_back(iBitrates[i]);
}
ShuttleGui S(this, eIsCreatingFromPrefs);
PopulateOrExchange(S);
@ -130,8 +159,13 @@ void ExportMP2Options::PopulateOrExchange(ShuttleGui & S)
{
S.StartMultiColumn(2, wxCENTER);
{
S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/MP2Bitrate"),
160, mBitRateNames, mBitRateLabels);
S.TieNumberAsChoice(
_("Bit Rate:"),
wxT("/FileFormats/MP2Bitrate"),
160,
BitRateNames,
&BitRateValues
);
}
S.EndMultiColumn();
}

View File

@ -112,16 +112,7 @@ enum MP3ChannelMode : unsigned {
};
enum : int {
QUALITY_0 = 0,
QUALITY_1 = 1,
QUALITY_2 = 2,
QUALITY_3 = 3,
QUALITY_4 = 4,
QUALITY_5 = 5,
QUALITY_6 = 6,
QUALITY_7 = 7,
QUALITY_8 = 8,
QUALITY_9 = 9,
ROUTINE_FAST = 0,
ROUTINE_STANDARD = 1,
@ -132,95 +123,93 @@ enum : int {
PRESET_MEDIUM = 3,
};
// Note: The label field is what will be written to preferences and carries
// no numerical significance. It is simply a means to look up a value
// in a table.
//
// The entries should be listed in order you want them to appear in the
// choice dropdown based on the name field.
typedef struct
{
wxString name;
int label;
} CHOICES;
static CHOICES fixRates[] =
{
static const wxArrayStringEx fixRateNames {
/* i18n-hint: kbps is the bitrate of the MP3 file, kilobits per second*/
{wxT(""), 320},
{wxT(""), 256},
{wxT(""), 224},
{wxT(""), 192},
{wxT(""), 160},
{wxT(""), 144},
{wxT(""), 128},
{wxT(""), 112},
{wxT(""), 96},
{wxT(""), 80},
{wxT(""), 64},
{wxT(""), 56},
{wxT(""), 48},
{wxT(""), 40},
{wxT(""), 32},
{wxT(""), 24},
{wxT(""), 16},
{wxT(""), 8}
XO("320 kbps"),
XO("256 kbps"),
XO("224 kbps"),
XO("192 kbps"),
XO("160 kbps"),
XO("144 kbps"),
XO("128 kbps"),
XO("112 kbps"),
XO("96 kbps"),
XO("80 kbps"),
XO("64 kbps"),
XO("56 kbps"),
XO("48 kbps"),
XO("40 kbps"),
XO("32 kbps"),
XO("24 kbps"),
XO("16 kbps"),
XO("8 kbps"),
};
static CHOICES varRates[] =
{
{wxT(""), QUALITY_0},
{wxT(""), QUALITY_1},
{wxT(""), QUALITY_2},
{wxT(""), QUALITY_3},
{wxT(""), QUALITY_4},
{wxT(""), QUALITY_5},
{wxT(""), QUALITY_6},
{wxT(""), QUALITY_7},
{wxT(""), QUALITY_8},
{wxT(""), QUALITY_9}
static const std::vector<int> fixRateValues {
320,
256,
224,
192,
160,
144,
128,
112,
96,
80,
64,
56,
48,
40,
32,
24,
16,
8,
};
static const wxChar *const varRatesNumbers[] = {
wxT("220-260"),
wxT("200-250"),
wxT("170-210"),
wxT("155-195"),
wxT("145-185"),
wxT("110-150"),
wxT("95-135"),
wxT("80-120"),
wxT("65-105"),
wxT("45-85")
};
static_assert( WXSIZEOF(varRates) == WXSIZEOF(varRatesNumbers),
"size mismatch" );
static CHOICES varModes[] =
{
{wxT(""), ROUTINE_FAST },
{wxT(""), ROUTINE_STANDARD}
static const wxArrayStringEx varRateNames {
XO("220-260 kbps (Best Quality)"),
XO("200-250 kbps"),
XO("170-210 kbps"),
XO("155-195 kbps"),
XO("145-185 kbps"),
XO("110-150 kbps"),
XO("95-135 kbps"),
XO("80-120 kbps"),
XO("65-105 kbps"),
XO("45-85 kbps (Smaller files)"),
};
static CHOICES setRates[] =
{
{wxT(""), PRESET_INSANE },
{wxT(""), PRESET_EXTREME },
{wxT(""), PRESET_STANDARD},
{wxT(""), PRESET_MEDIUM }
static const wxArrayStringEx varModeNames {
XO("Fast"),
XO("Standard"),
};
static CHOICES sampRates[] =
{
{wxT(""), 8000 },
{wxT(""), 11025 },
{wxT(""), 12000 },
{wxT(""), 16000 },
{wxT(""), 22050 },
{wxT(""), 24000 },
{wxT(""), 32000 },
{wxT(""), 44100 },
{wxT(""), 48000 }
static const wxArrayStringEx setRateNames {
/* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/
XO("Insane, 320 kbps"),
XO("Extreme, 220-260 kbps"),
XO("Standard, 170-210 kbps"),
XO("Medium, 145-185 kbps"),
};
static const wxArrayStringEx setRateNamesShort {
/* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/
XO("Insane"),
XO("Extreme"),
XO("Standard"),
XO("Medium"),
};
static const std::vector< int > sampRates {
8000,
11025,
12000,
16000,
22050,
24000,
32000,
44100,
48000,
};
#define ID_SET 7000
@ -230,33 +219,6 @@ static CHOICES sampRates[] =
#define ID_QUALITY 7004
#define ID_MONO 7005
static void InitMP3_Statics()
{
for (size_t i=0; i < WXSIZEOF(fixRates); i++)
fixRates[i].name = wxString::Format(_("%d kbps"), fixRates[i].label);
varRates[0].name = wxString::Format(
_("%s kbps (Best Quality)"), varRatesNumbers[0] );
for (size_t i = 1; i < WXSIZEOF(varRates) - 1; i++)
varRates[i].name = wxString::Format( _("%s kbps"), varRatesNumbers[i] );
varRates[9].name = wxString::Format(
_("%s kbps (Smaller files)"), varRatesNumbers[9] );
varModes[0].name = _("Fast");
varModes[1].name = _("Standard");
/* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/
setRates[0].name = _("Insane, 320 kbps");
setRates[1].name = _("Extreme, 220-260 kbps");
setRates[2].name = _("Standard, 170-210 kbps");
setRates[3].name = _("Medium, 145-185 kbps");
for (size_t i=0; i < WXSIZEOF(sampRates); i++)
sampRates[i].name = wxString::Format( wxT("%d"), sampRates[i].label );
}
class ExportMP3Options final : public wxPanelWrapper
{
public:
@ -275,10 +237,7 @@ public:
void OnQuality(wxCommandEvent& evt);
void OnMono(wxCommandEvent& evt);
void LoadNames(CHOICES *choices, int count);
wxArrayString GetNames(CHOICES *choices, int count);
std::vector<int> GetLabels(CHOICES *choices, int count);
int FindIndex(CHOICES *choices, int cnt, int needle, int def);
void LoadNames(const wxArrayStringEx &choices);
private:
@ -314,8 +273,6 @@ END_EVENT_TABLE()
ExportMP3Options::ExportMP3Options(wxWindow *parent, int WXUNUSED(format))
: wxPanelWrapper(parent, wxID_ANY)
{
InitMP3_Statics();
mSetRate = gPrefs->Read(wxT("/FileFormats/MP3SetRate"), PRESET_STANDARD);
mVbrRate = gPrefs->Read(wxT("/FileFormats/MP3VbrRate"), QUALITY_2);
mAbrRate = gPrefs->Read(wxT("/FileFormats/MP3AbrRate"), 192);
@ -391,48 +348,48 @@ void ExportMP3Options::PopulateOrExchange(ShuttleGui & S)
}
S.EndHorizontalLay();
CHOICES *choices;
int cnt;
const wxArrayStringEx *choices = nullptr;
const std::vector< int > *codes = nullptr;
bool enable;
int defrate;
if (mSET->GetValue()) {
choices = setRates;
cnt = WXSIZEOF(setRates);
choices = &setRateNames;
enable = true;
defrate = mSetRate;
}
else if (mVBR->GetValue()) {
choices = varRates;
cnt = WXSIZEOF(varRates);
choices = &varRateNames;
enable = true;
defrate = mVbrRate;
}
else if (mABR->GetValue()) {
choices = fixRates;
cnt = WXSIZEOF(fixRates);
choices = &fixRateNames;
codes = &fixRateValues;
enable = false;
defrate = mAbrRate;
}
else {
mCBR->SetValue(true);
choices = fixRates;
cnt = WXSIZEOF(fixRates);
choices = &fixRateNames;
codes = &fixRateValues;
enable = false;
defrate = mCbrRate;
}
mRate = S.Id(ID_QUALITY).TieChoice(_("Quality"),
wxT("/FileFormats/MP3Bitrate"),
defrate,
GetNames(choices, cnt),
GetLabels(choices, cnt));
mMode = S.TieChoice(_("Variable Speed:"),
wxT("/FileFormats/MP3VarMode"),
ROUTINE_FAST,
GetNames(varModes, WXSIZEOF(varModes)),
GetLabels(varModes, WXSIZEOF(varModes)));
mRate = S.Id(ID_QUALITY).TieNumberAsChoice(
_("Quality"),
wxT("/FileFormats/MP3Bitrate"),
defrate,
*choices,
codes
);
mMode = S.TieNumberAsChoice(
_("Variable Speed:"),
wxT("/FileFormats/MP3VarMode"),
ROUTINE_FAST,
varModeNames );
mMode->Enable(enable);
S.AddPrompt(_("Channel Mode:"));
@ -484,13 +441,28 @@ bool ExportMP3Options::TransferDataFromWindow()
return true;
}
namespace {
int ValidateValue( int nValues, int value, int defaultValue )
{
return (value >= 0 && value < nValues) ? value : defaultValue;
}
int ValidateValue( const std::vector<int> &values, int value, int defaultValue )
{
auto start = values.begin(), finish = values.end(),
iter = std::find( start, finish, value );
return ( iter != finish ) ? value : defaultValue;
}
}
///
///
void ExportMP3Options::OnSET(wxCommandEvent& WXUNUSED(event))
{
LoadNames(setRates, WXSIZEOF(setRates));
LoadNames(setRateNames);
mRate->SetSelection(FindIndex(setRates, WXSIZEOF(setRates), mSetRate, 2));
mRate->SetSelection(ValidateValue(setRateNames.size(), mSetRate, 2));
mRate->Refresh();
mMode->Enable(true);
}
@ -499,9 +471,9 @@ void ExportMP3Options::OnSET(wxCommandEvent& WXUNUSED(event))
///
void ExportMP3Options::OnVBR(wxCommandEvent& WXUNUSED(event))
{
LoadNames(varRates, WXSIZEOF(varRates));
LoadNames(varRateNames);
mRate->SetSelection(FindIndex(varRates, WXSIZEOF(varRates), mVbrRate, 2));
mRate->SetSelection(ValidateValue(varRateNames.size(), mVbrRate, 2));
mRate->Refresh();
mMode->Enable(true);
}
@ -510,9 +482,9 @@ void ExportMP3Options::OnVBR(wxCommandEvent& WXUNUSED(event))
///
void ExportMP3Options::OnABR(wxCommandEvent& WXUNUSED(event))
{
LoadNames(fixRates, WXSIZEOF(fixRates));
LoadNames(fixRateNames);
mRate->SetSelection(FindIndex(fixRates, WXSIZEOF(fixRates), mAbrRate, 10));
mRate->SetSelection(ValidateValue(fixRateValues, mAbrRate, 10));
mRate->Refresh();
mMode->Enable(false);
}
@ -521,9 +493,9 @@ void ExportMP3Options::OnABR(wxCommandEvent& WXUNUSED(event))
///
void ExportMP3Options::OnCBR(wxCommandEvent& WXUNUSED(event))
{
LoadNames(fixRates, WXSIZEOF(fixRates));
LoadNames(fixRateNames);
mRate->SetSelection(FindIndex(fixRates, WXSIZEOF(fixRates), mCbrRate, 10));
mRate->SetSelection(ValidateValue(fixRateValues, mCbrRate, 10));
mRate->Refresh();
mMode->Enable(false);
}
@ -533,16 +505,16 @@ void ExportMP3Options::OnQuality(wxCommandEvent& WXUNUSED(event))
int sel = mRate->GetSelection();
if (mSET->GetValue()) {
mSetRate = setRates[sel].label;
mSetRate = sel;
}
else if (mVBR->GetValue()) {
mVbrRate = varRates[sel].label;
mVbrRate = sel;
}
else if (mABR->GetValue()) {
mAbrRate = fixRates[sel].label;
mAbrRate = fixRateValues[ sel ];
}
else {
mCbrRate = fixRates[sel].label;
mCbrRate = fixRateValues[ sel ];
}
}
@ -557,47 +529,11 @@ void ExportMP3Options::OnMono(wxCommandEvent& /*evt*/)
gPrefs->Flush();
}
void ExportMP3Options::LoadNames(CHOICES *choices, int count)
void ExportMP3Options::LoadNames(const wxArrayStringEx &names)
{
mRate->Clear();
for (int i = 0; i < count; i++)
{
mRate->Append(choices[i].name);
}
}
wxArrayString ExportMP3Options::GetNames(CHOICES *choices, int count)
{
wxArrayString names;
for (int i = 0; i < count; i++) {
names.push_back(choices[i].name);
}
return names;
}
std::vector<int> ExportMP3Options::GetLabels(CHOICES *choices, int count)
{
std::vector<int> labels;
for (int i = 0; i < count; i++) {
labels.push_back(choices[i].label);
}
return labels;
}
int ExportMP3Options::FindIndex(CHOICES *choices, int cnt, int needle, int def)
{
for (int i = 0; i < cnt; i++) {
if (choices[i].label == needle) {
return i;
}
}
return def;
for (const auto &name : names)
mRate->Append( GetCustomTranslation( name ) );
}
//----------------------------------------------------------------------------
@ -1732,8 +1668,6 @@ public:
private:
int FindValue(CHOICES *choices, int cnt, int needle, int def);
wxString FindName(CHOICES *choices, int cnt, int needle);
int AskResample(int bitrate, int rate, int lowrate, int highrate);
unsigned long AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
#ifdef USE_LIBID3TAG
@ -1745,7 +1679,6 @@ private:
ExportMP3::ExportMP3()
: ExportPlugin()
{
InitMP3_Statics();
AddFormat();
SetFormat(wxT("MP3"),0);
AddExtension(wxT("mp3"),0);
@ -1840,19 +1773,19 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
// Set the bitrate/quality and mode
if (rmode == MODE_SET) {
int q = FindValue(setRates, WXSIZEOF(setRates), brate, PRESET_STANDARD);
int r = FindValue(varModes, WXSIZEOF(varModes), vmode, ROUTINE_FAST);
brate = ValidateValue(setRateNames.size(), brate, PRESET_STANDARD);
int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST );
exporter.SetMode(MODE_SET);
exporter.SetQuality(q, r);
exporter.SetQuality(brate, r);
}
else if (rmode == MODE_VBR) {
int q = FindValue(varRates, WXSIZEOF(varRates), brate, QUALITY_2);
int r = FindValue(varModes, WXSIZEOF(varModes), vmode, ROUTINE_FAST);
brate = ValidateValue( varRateNames.size(), brate, QUALITY_2 );
int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST );
exporter.SetMode(MODE_VBR);
exporter.SetQuality(q, r);
exporter.SetQuality(brate, r);
}
else if (rmode == MODE_ABR) {
bitrate = FindValue(fixRates, WXSIZEOF(fixRates), brate, 128);
bitrate = brate = ValidateValue(fixRateValues, brate, 128);
exporter.SetMode(MODE_ABR);
exporter.SetBitrate(bitrate);
@ -1864,7 +1797,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
}
}
else {
bitrate = FindValue(fixRates, WXSIZEOF(fixRates), brate, 128);
bitrate = brate = ValidateValue(fixRateValues, brate, 128);
exporter.SetMode(MODE_CBR);
exporter.SetBitrate(bitrate);
@ -1877,7 +1810,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
}
// Verify sample rate
if (FindName(sampRates, WXSIZEOF(sampRates), rate).empty() ||
if (!make_iterator_range( sampRates ).contains( rate ) ||
(rate < lowrate) || (rate > highrate)) {
rate = AskResample(bitrate, rate, lowrate, highrate);
if (rate == 0) {
@ -1949,13 +1882,13 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
title.Printf(selectionOnly ?
_("Exporting selected audio with %s preset") :
_("Exporting the audio with %s preset"),
FindName(setRates, WXSIZEOF(setRates), brate));
setRateNamesShort[brate]);
}
else if (rmode == MODE_VBR) {
title.Printf(selectionOnly ?
_("Exporting selected audio with VBR quality %s") :
_("Exporting the audio with VBR quality %s"),
FindName(varRates, WXSIZEOF(varRates), brate));
varRateNames[brate]);
}
else {
title.Printf(selectionOnly ?
@ -2063,28 +1996,6 @@ wxWindow *ExportMP3::OptionsCreate(wxWindow *parent, int format)
return safenew ExportMP3Options(parent, format);
}
int ExportMP3::FindValue(CHOICES *choices, int cnt, int needle, int def)
{
for (int i = 0; i < cnt; i++) {
if (choices[i].label == needle) {
return needle;
}
}
return def;
}
wxString ExportMP3::FindName(CHOICES *choices, int cnt, int needle)
{
for (int i = 0; i < cnt; i++) {
if (choices[i].label == needle) {
return choices[i].name.BeforeFirst(wxT(','));
}
}
return wxT("");
}
int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate)
{
wxDialogWrapper d(nullptr, wxID_ANY, wxString(_("Invalid sample rate")));
@ -2114,12 +2025,12 @@ int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate)
wxArrayStringEx choices;
int selected = -1;
for (size_t i = 0; i < WXSIZEOF(sampRates); i++) {
int label = sampRates[i].label;
for (size_t ii = 0, nn = sampRates.size(); ii < nn; ++ii) {
int label = sampRates[ii];
if (label >= lowrate && label <= highrate) {
choices.push_back(sampRates[i].name);
choices.push_back( wxString::Format( "%d", label ) );
if (label <= rate) {
selected = i;
selected = ii;
}
}
}