mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-15 08:07:41 +02:00
Non-quantitative enum preferences persist as strings not numbers...
... The one unusual choice control in Preferences that really is quantitative is for sample rate in Quality. And that one is changed to be treated as not an enum preference.
This commit is contained in:
commit
0798681317
@ -184,12 +184,12 @@ inline size_t limitSampleBufferSize( size_t bufferSize, sampleCount limit )
|
||||
// ----------------------------------------------------------------------------
|
||||
// Supported sample formats
|
||||
// ----------------------------------------------------------------------------
|
||||
typedef enum
|
||||
enum sampleFormat : unsigned
|
||||
{
|
||||
int16Sample = 0x00020001,
|
||||
int24Sample = 0x00040001,
|
||||
floatSample = 0x0004000F
|
||||
} sampleFormat;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Provide the number of bytes a specific sample will take
|
||||
|
@ -447,6 +447,7 @@ TimeTrack and AudioIOListener and whether the playback is looped.
|
||||
#include "WaveTrack.h"
|
||||
#include "AutoRecovery.h"
|
||||
|
||||
#include "prefs/QualityPrefs.h"
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "widgets/Meter.h"
|
||||
#include "widgets/ErrorDialog.h"
|
||||
@ -1825,8 +1826,7 @@ void AudioIO::StartMonitoring(double sampleRate)
|
||||
|
||||
bool success;
|
||||
long captureChannels;
|
||||
sampleFormat captureFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
auto captureFormat = QualityPrefs::SampleFormatChoice();
|
||||
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &captureChannels, 2L);
|
||||
gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &mSoftwarePlaythrough, false);
|
||||
int playbackChannels = 0;
|
||||
|
@ -325,17 +325,17 @@ void Dither::Apply(enum DitherType ditherType,
|
||||
// We must do dithering
|
||||
switch (ditherType)
|
||||
{
|
||||
case none:
|
||||
case DitherType::none:
|
||||
DITHER(NoDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
|
||||
break;
|
||||
case rectangle:
|
||||
case DitherType::rectangle:
|
||||
DITHER(RectangleDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
|
||||
break;
|
||||
case triangle:
|
||||
case DitherType::triangle:
|
||||
Reset(); // reset dither filter for this NEW conversion
|
||||
DITHER(TriangleDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
|
||||
break;
|
||||
case shaped:
|
||||
case DitherType::shaped:
|
||||
Reset(); // reset dither filter for this NEW conversion
|
||||
DITHER(ShapedDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
|
||||
break;
|
||||
|
@ -13,15 +13,16 @@
|
||||
#include "SampleFormat.h"
|
||||
|
||||
|
||||
/// These ditherers are currently available:
|
||||
enum class DitherType : unsigned {
|
||||
none = 0, rectangle = 1, triangle = 2, shaped = 3 };
|
||||
|
||||
class Dither
|
||||
{
|
||||
public:
|
||||
/// Default constructor
|
||||
Dither();
|
||||
|
||||
/// These ditherers are currently available:
|
||||
enum DitherType { none = 0, rectangle = 1, triangle = 2, shaped = 3};
|
||||
|
||||
/// Reset state of the dither.
|
||||
void Reset();
|
||||
|
||||
|
@ -6817,10 +6817,8 @@ void AudacityProject::OnZoomToggle(const CommandContext &WXUNUSED(context) )
|
||||
// const double origWidth = GetScreenEndTime() - origLeft;
|
||||
|
||||
// Choose the zoom that is most different to the current zoom.
|
||||
double Zoom1 = GetZoomOfPref(
|
||||
wxT("/GUI/ZoomPreset1"), WaveTrack::kZoomDefault );
|
||||
double Zoom2 = GetZoomOfPref(
|
||||
wxT("/GUI/ZoomPreset2"), WaveTrack::kZoom4To1 );
|
||||
double Zoom1 = GetZoomOfPreset( TracksPrefs::Zoom1Choice() );
|
||||
double Zoom2 = GetZoomOfPreset( TracksPrefs::Zoom2Choice() );
|
||||
double Z = mViewInfo.GetZoom();// Current Zoom.
|
||||
double ChosenZoom = abs(log(Zoom1 / Z)) > abs(log( Z / Zoom2)) ? Zoom1:Zoom2;
|
||||
|
||||
|
@ -341,3 +341,90 @@ void FinishPreferences()
|
||||
gPrefs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//////////
|
||||
wxString EnumSetting::Read() const
|
||||
{
|
||||
const auto &defaultValue = Default().Internal();
|
||||
wxString value;
|
||||
if ( !gPrefs->Read(mKey, &value, defaultValue) )
|
||||
if (!mMigrated) {
|
||||
const_cast<EnumSetting*>(this)->Migrate( value );
|
||||
mMigrated = true;
|
||||
}
|
||||
|
||||
// Remap to default if the string is not known -- this avoids surprises
|
||||
// in case we try to interpret config files from future versions
|
||||
auto index = Find( value );
|
||||
if ( index >= mnSymbols )
|
||||
value = defaultValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t EnumSetting::Find( const wxString &value ) const
|
||||
{
|
||||
return size_t(
|
||||
std::find( begin(), end(), IdentInterfaceSymbol{ value, {} } )
|
||||
- mSymbols );
|
||||
}
|
||||
|
||||
void EnumSetting::Migrate( wxString &value )
|
||||
{
|
||||
}
|
||||
|
||||
bool EnumSetting::Write( const wxString &value )
|
||||
{
|
||||
auto index = Find( value );
|
||||
if (index >= mnSymbols)
|
||||
return false;
|
||||
|
||||
auto result = gPrefs->Write( mKey, value );
|
||||
mMigrated = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
int EncodedEnumSetting::ReadInt() const
|
||||
{
|
||||
if (!mIntValues)
|
||||
return 0;
|
||||
|
||||
auto index = Find( Read() );
|
||||
wxASSERT( index < mnSymbols );
|
||||
return mIntValues[ index ];
|
||||
}
|
||||
|
||||
size_t EncodedEnumSetting::FindInt( int code ) const
|
||||
{
|
||||
if (!mIntValues)
|
||||
return mnSymbols;
|
||||
|
||||
return size_t(
|
||||
std::find( mIntValues, mIntValues + mnSymbols, code )
|
||||
- mIntValues );
|
||||
}
|
||||
|
||||
void EncodedEnumSetting::Migrate( wxString &value )
|
||||
{
|
||||
int intValue = 0;
|
||||
if ( !mOldKey.empty() &&
|
||||
gPrefs->Read(mOldKey, &intValue, 0) ) {
|
||||
// Make the migration, only once and persistently.
|
||||
// Do not DELETE the old key -- let that be read if user downgrades
|
||||
// Audacity. But further changes will be stored only to the NEW key
|
||||
// and won't be seen then.
|
||||
auto index = FindInt( intValue );
|
||||
if ( index >= mnSymbols )
|
||||
index = mDefaultSymbol;
|
||||
value = mSymbols[index].Internal();
|
||||
Write(value);
|
||||
gPrefs->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
bool EncodedEnumSetting::WriteInt( int code ) // you flush gPrefs afterward
|
||||
{
|
||||
auto index = FindInt( code );
|
||||
if ( index >= mnSymbols )
|
||||
return false;
|
||||
return Write( mSymbols[index].Internal() );
|
||||
}
|
||||
|
81
src/Prefs.h
81
src/Prefs.h
@ -30,6 +30,7 @@
|
||||
#define __AUDACITY_PREFS__
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "../include/audacity/IdentInterface.h"
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/fileconf.h>
|
||||
@ -40,4 +41,84 @@ void FinishPreferences();
|
||||
extern AUDACITY_DLL_API wxFileConfig *gPrefs;
|
||||
extern int gMenusDirty;
|
||||
|
||||
// Packages a table of user-visible choices each with an internal code string,
|
||||
// a preference key path,
|
||||
// and a default choice
|
||||
class EnumSetting
|
||||
{
|
||||
public:
|
||||
EnumSetting(
|
||||
const wxString &key,
|
||||
const IdentInterfaceSymbol symbols[], size_t nSymbols,
|
||||
size_t defaultSymbol
|
||||
)
|
||||
: mKey{ key }
|
||||
|
||||
, mSymbols{ symbols }
|
||||
, mnSymbols{ nSymbols }
|
||||
|
||||
, mDefaultSymbol{ defaultSymbol }
|
||||
{
|
||||
wxASSERT( defaultSymbol < nSymbols );
|
||||
}
|
||||
|
||||
const wxString &Key() const { return mKey; }
|
||||
const IdentInterfaceSymbol &Default() const
|
||||
{ return mSymbols[mDefaultSymbol]; }
|
||||
const IdentInterfaceSymbol *begin() const { return mSymbols; }
|
||||
const IdentInterfaceSymbol *end() const { return mSymbols + mnSymbols; }
|
||||
|
||||
wxString Read() const;
|
||||
bool Write( const wxString &value ); // you flush gPrefs afterward
|
||||
|
||||
protected:
|
||||
size_t Find( const wxString &value ) const;
|
||||
virtual void Migrate( wxString& );
|
||||
|
||||
const wxString mKey;
|
||||
|
||||
const IdentInterfaceSymbol *mSymbols;
|
||||
const size_t mnSymbols;
|
||||
|
||||
// stores an internal value
|
||||
mutable bool mMigrated { false };
|
||||
|
||||
const size_t mDefaultSymbol;
|
||||
};
|
||||
|
||||
// Extends EnumSetting with a corresponding table of integer codes
|
||||
// (generally not equal to their table positions),
|
||||
// and optionally an old preference key path that stored integer codes, to be
|
||||
// migrated into one that stores internal string values instead
|
||||
class EncodedEnumSetting : public EnumSetting
|
||||
{
|
||||
public:
|
||||
EncodedEnumSetting(
|
||||
const wxString &key,
|
||||
const IdentInterfaceSymbol symbols[], size_t nSymbols,
|
||||
size_t defaultSymbol,
|
||||
|
||||
const int intValues[] = nullptr, // must have same size as symbols
|
||||
const wxString &oldKey = {}
|
||||
)
|
||||
: EnumSetting{ key, symbols, nSymbols, defaultSymbol }
|
||||
, mIntValues{ intValues }
|
||||
, mOldKey{ oldKey }
|
||||
{
|
||||
wxASSERT( mIntValues );
|
||||
}
|
||||
|
||||
// Read and write the encoded values
|
||||
virtual int ReadInt() const;
|
||||
bool WriteInt( int code ); // you flush gPrefs afterward
|
||||
|
||||
protected:
|
||||
size_t FindInt( int code ) const;
|
||||
void Migrate( wxString& ) override;
|
||||
|
||||
private:
|
||||
const int *mIntValues;
|
||||
const wxString mOldKey;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -166,6 +166,8 @@ scroll information. It also has some status flags.
|
||||
#include "commands/CommandType.h"
|
||||
#include "commands/CommandContext.h"
|
||||
|
||||
#include "prefs/QualityPrefs.h"
|
||||
|
||||
#include "../images/AudacityLogoAlpha.xpm"
|
||||
|
||||
std::shared_ptr<TrackList> AudacityProject::msClipboard{ TrackList::Create() };
|
||||
@ -917,8 +919,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
||||
mViewInfo(0.0, 1.0, ZoomInfo::GetDefaultZoom()),
|
||||
mbLoadedFromAup( false ),
|
||||
mRate((double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), AudioIO::GetOptimalSupportedSampleRate())),
|
||||
mDefaultFormat((sampleFormat) gPrefs->
|
||||
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample)),
|
||||
mDefaultFormat(QualityPrefs::SampleFormatChoice()),
|
||||
mSnapTo(gPrefs->Read(wxT("/SnapTo"), SNAP_OFF)),
|
||||
mSelectionFormat(gPrefs->Read(wxT("/SelectionFormat"), wxT(""))),
|
||||
mFrequencySelectionFormatName(gPrefs->Read(wxT("/FrequencySelectionFormatName"), wxT(""))),
|
||||
@ -1305,7 +1306,7 @@ void AudacityProject::UpdatePrefsVariables()
|
||||
// gPrefs->Read(wxT("/GUI/UpdateSpectrogram"), &mViewInfo.bUpdateSpectrogram, true);
|
||||
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), &mRate, AudioIO::GetOptimalSupportedSampleRate());
|
||||
mDefaultFormat = (sampleFormat) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
mDefaultFormat = QualityPrefs::SampleFormatChoice();
|
||||
|
||||
gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &mSeekShort, 1.0);
|
||||
gPrefs->Read(wxT("/AudioIO/SeekLongPeriod"), &mSeekLong, 15.0);
|
||||
@ -5887,8 +5888,7 @@ wxString AudacityProject::GetHoursMinsString(int iMinutes)
|
||||
int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels) {
|
||||
|
||||
// Obtain the current settings
|
||||
sampleFormat oCaptureFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
auto oCaptureFormat = QualityPrefs::SampleFormatChoice();
|
||||
if (lCaptureChannels == 0) {
|
||||
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &lCaptureChannels, 2L);
|
||||
}
|
||||
@ -6014,12 +6014,6 @@ double AudacityProject::GetZoomOfPreset( int preset ){
|
||||
return result;
|
||||
}
|
||||
|
||||
double AudacityProject::GetZoomOfPref( const wxString & PresetPrefName, int defaultPreset ){
|
||||
int preset=defaultPreset;
|
||||
gPrefs->Read( PresetPrefName, &preset, defaultPreset );
|
||||
return GetZoomOfPreset( preset );
|
||||
}
|
||||
|
||||
AudacityProject::PlaybackScroller::PlaybackScroller(AudacityProject *project)
|
||||
: mProject(project)
|
||||
{
|
||||
|
@ -600,7 +600,6 @@ public:
|
||||
double GetZoomOfToFit();
|
||||
double GetZoomOfSelection();
|
||||
double GetZoomOfPreset(int preset );
|
||||
double GetZoomOfPref( const wxString & PresetPrefName, int defaultPreset );
|
||||
|
||||
public:
|
||||
bool IsSoloSimple() const { return mSoloPref == wxT("Simple"); }
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "Prefs.h"
|
||||
#include "TranslatableStringArray.h"
|
||||
#include "Internat.h"
|
||||
#include "../include/audacity/IdentInterface.h"
|
||||
|
||||
#include <soxr.h>
|
||||
|
||||
@ -50,47 +51,57 @@ Resample::~Resample()
|
||||
{
|
||||
}
|
||||
|
||||
int Resample::GetNumMethods() { return 4; }
|
||||
//////////
|
||||
static const IdentInterfaceSymbol methodNames[] = {
|
||||
{ wxT("LowQuality"), XO("Low Quality (Fastest)") },
|
||||
{ wxT("MediumQuality"), XO("Medium Quality") },
|
||||
{ wxT("HighQuality"), XO("High Quality") },
|
||||
{ wxT("BestQuality"), XO("Best Quality (Slowest)") }
|
||||
};
|
||||
|
||||
wxString Resample::GetMethodName(int index)
|
||||
static const size_t numMethods = WXSIZEOF(methodNames);
|
||||
|
||||
static const wxString fastMethodKey =
|
||||
wxT("/Quality/LibsoxrSampleRateConverterChoice");
|
||||
|
||||
static const wxString bestMethodKey =
|
||||
wxT("/Quality/LibsoxrHQSampleRateConverterChoice");
|
||||
|
||||
static const wxString oldFastMethodKey =
|
||||
wxT("/Quality/LibsoxrSampleRateConverter");
|
||||
|
||||
static const wxString oldBestMethodKey =
|
||||
wxT("/Quality/LibsoxrHQSampleRateConverter");
|
||||
|
||||
static const size_t fastMethodDefault = 1; // Medium Quality
|
||||
static const size_t bestMethodDefault = 3; // Best Quality
|
||||
|
||||
static const int intChoicesMethod[] = {
|
||||
0, 1, 2, 3
|
||||
};
|
||||
|
||||
static_assert( WXSIZEOF(intChoicesMethod) == numMethods, "size mismatch" );
|
||||
|
||||
EncodedEnumSetting Resample::FastMethodSetting{
|
||||
fastMethodKey,
|
||||
methodNames, numMethods,
|
||||
fastMethodDefault,
|
||||
|
||||
intChoicesMethod,
|
||||
oldFastMethodKey
|
||||
};
|
||||
|
||||
EncodedEnumSetting Resample::BestMethodSetting
|
||||
{
|
||||
static const wxString soxr_method_names[] = {
|
||||
XO("Low Quality (Fastest)"),
|
||||
XO("Medium Quality"),
|
||||
XO("High Quality"),
|
||||
XO("Best Quality (Slowest)")
|
||||
};
|
||||
bestMethodKey,
|
||||
methodNames, numMethods,
|
||||
bestMethodDefault,
|
||||
|
||||
wxASSERT( GetNumMethods() ==
|
||||
sizeof(soxr_method_names) / sizeof(*soxr_method_names) );
|
||||
|
||||
class MethodNamesArray final : public TranslatableStringArray
|
||||
{
|
||||
void Populate() override
|
||||
{
|
||||
for (auto &name : soxr_method_names)
|
||||
mContents.push_back( wxGetTranslation( name ) );
|
||||
}
|
||||
};
|
||||
|
||||
static MethodNamesArray theArray;
|
||||
|
||||
return theArray.Get()[ index ];
|
||||
}
|
||||
|
||||
const wxString Resample::GetFastMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrSampleRateConverter");
|
||||
}
|
||||
|
||||
const wxString Resample::GetBestMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrHQSampleRateConverter");
|
||||
}
|
||||
|
||||
int Resample::GetFastMethodDefault() {return 1;}
|
||||
int Resample::GetBestMethodDefault() {return 3;}
|
||||
intChoicesMethod,
|
||||
oldBestMethodKey
|
||||
};
|
||||
|
||||
//////////
|
||||
std::pair<size_t, size_t>
|
||||
Resample::Process(double factor,
|
||||
float *inBuffer,
|
||||
@ -121,7 +132,7 @@ std::pair<size_t, size_t>
|
||||
void Resample::SetMethod(const bool useBestMethod)
|
||||
{
|
||||
if (useBestMethod)
|
||||
mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault());
|
||||
mMethod = BestMethodSetting.ReadInt();
|
||||
else
|
||||
mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault());
|
||||
mMethod = FastMethodSetting.ReadInt();
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "SampleFormat.h"
|
||||
|
||||
class EncodedEnumSetting;
|
||||
|
||||
struct soxr;
|
||||
extern "C" void soxr_delete(soxr*);
|
||||
struct soxr_deleter {
|
||||
@ -43,13 +45,8 @@ class Resample final
|
||||
Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor);
|
||||
~Resample();
|
||||
|
||||
static int GetNumMethods();
|
||||
static wxString GetMethodName(int index);
|
||||
|
||||
static const wxString GetFastMethodKey();
|
||||
static const wxString GetBestMethodKey();
|
||||
static int GetFastMethodDefault();
|
||||
static int GetBestMethodDefault();
|
||||
static EncodedEnumSetting FastMethodSetting;
|
||||
static EncodedEnumSetting BestMethodSetting;
|
||||
|
||||
/** @brief Main processing function. Resamples from the input buffer to the
|
||||
* output buffer.
|
||||
|
@ -44,19 +44,17 @@
|
||||
#include "Prefs.h"
|
||||
#include "Dither.h"
|
||||
#include "Internat.h"
|
||||
#include "prefs/QualityPrefs.h"
|
||||
|
||||
static Dither::DitherType gLowQualityDither = Dither::none;
|
||||
static Dither::DitherType gHighQualityDither = Dither::none;
|
||||
static DitherType gLowQualityDither = DitherType::none;
|
||||
static DitherType gHighQualityDither = DitherType::none;
|
||||
static Dither gDitherAlgorithm;
|
||||
|
||||
void InitDitherers()
|
||||
{
|
||||
// Read dither preferences
|
||||
gLowQualityDither = (Dither::DitherType)
|
||||
gPrefs->Read(wxT("/Quality/DitherAlgorithm"), (long)Dither::none);
|
||||
|
||||
gHighQualityDither = (Dither::DitherType)
|
||||
gPrefs->Read(wxT("/Quality/HQDitherAlgorithm"), (long)Dither::shaped);
|
||||
gLowQualityDither = QualityPrefs::FastDitherChoice();
|
||||
gHighQualityDither = QualityPrefs::BestDitherChoice();
|
||||
}
|
||||
|
||||
const wxChar *GetSampleFormatStr(sampleFormat format)
|
||||
@ -120,6 +118,6 @@ void CopySamplesNoDither(samplePtr src, sampleFormat srcFormat,
|
||||
unsigned int dstStride /* = 1 */)
|
||||
{
|
||||
gDitherAlgorithm.Apply(
|
||||
Dither::none,
|
||||
DitherType::none,
|
||||
src, srcFormat, dst, dstFormat, len, srcStride, dstStride);
|
||||
}
|
||||
|
@ -1040,7 +1040,7 @@ void Sequence::WriteXML(XMLWriter &xmlFile) const
|
||||
xmlFile.StartTag(wxT("sequence"));
|
||||
|
||||
xmlFile.WriteAttr(wxT("maxsamples"), mMaxSamples);
|
||||
xmlFile.WriteAttr(wxT("sampleformat"), mSampleFormat);
|
||||
xmlFile.WriteAttr(wxT("sampleformat"), (size_t)mSampleFormat);
|
||||
xmlFile.WriteAttr(wxT("numsamples"), mNumSamples.as_long_long() );
|
||||
|
||||
for (b = 0; b < mBlock.size(); b++) {
|
||||
|
@ -95,6 +95,7 @@ for registering for changes.
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "Experimental.h"
|
||||
#include "Prefs.h"
|
||||
#include "Shuttle.h"
|
||||
#include "ShuttleGui.h"
|
||||
|
||||
@ -106,6 +107,7 @@ for registering for changes.
|
||||
#include <wx/treectrl.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include "../include/audacity/IdentInterface.h"
|
||||
#include "Internat.h"
|
||||
#include "WrappedType.h"
|
||||
#include "widgets/wxPanelWrapper.h"
|
||||
@ -1847,32 +1849,55 @@ wxTextCtrl * ShuttleGuiBase::TieNumericTextBox(
|
||||
return pText;
|
||||
}
|
||||
|
||||
/// Variant of the standard TieChoice which does the two step exchange
|
||||
/// between gui and stack variable and stack variable and shuttle.
|
||||
/// @param Prompt The prompt shown beside the control.
|
||||
/// @param Setting Encapsulates setting name, internal and visible
|
||||
/// choice strings, and a designation of one of
|
||||
/// those as default.
|
||||
wxChoice *ShuttleGuiBase::TieChoice(
|
||||
const wxString &Prompt,
|
||||
EnumSetting &enumSetting )
|
||||
{
|
||||
// Do this to force any needed migrations first
|
||||
enumSetting.Read();
|
||||
|
||||
wxArrayString visibleChoices, internalChoices;
|
||||
for (const auto &ident : enumSetting) {
|
||||
visibleChoices.push_back( ident.Translation() );
|
||||
internalChoices.push_back( ident.Internal() );
|
||||
}
|
||||
return TieChoice(
|
||||
Prompt, enumSetting.Key(), enumSetting.Default().Translation(),
|
||||
visibleChoices, internalChoices );
|
||||
}
|
||||
|
||||
/// Variant of the standard TieChoice which does the two step exchange
|
||||
/// between gui and stack variable and stack variable and shuttle.
|
||||
/// @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 TranslatedChoices The corresponding values (as a string array)
|
||||
/// @param InternalChoices The corresponding values (as a string array)
|
||||
wxChoice * ShuttleGuiBase::TieChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const wxString &Default,
|
||||
const wxArrayString & Choices,
|
||||
const wxArrayString & TranslatedChoices)
|
||||
const wxArrayString & InternalChoices)
|
||||
{
|
||||
wxChoice * pChoice=(wxChoice*)NULL;
|
||||
|
||||
int TempIndex=0;
|
||||
// int TempIndex = TranslateToIndex( Default, TranslatedChoices );
|
||||
// int TempIndex = TranslateToIndex( Default, InternalChoices );
|
||||
wxString TempStr = Default;
|
||||
WrappedType WrappedRef( TempStr );
|
||||
// Get from prefs does 1 and 2.
|
||||
// Put to prefs does 2 and 3.
|
||||
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Index from Prefs.
|
||||
if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, TranslatedChoices ); // To an index
|
||||
if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, InternalChoices ); // To an index
|
||||
if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, &Choices ); // Get/Put index from GUI.
|
||||
if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, TranslatedChoices ); // To a string
|
||||
if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, InternalChoices ); // To a string
|
||||
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs.
|
||||
return pChoice;
|
||||
}
|
||||
@ -1885,13 +1910,13 @@ wxChoice * ShuttleGuiBase::TieChoice(
|
||||
/// @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 TranslatedChoices The correcponding values (as an integer array)
|
||||
/// @param InternalChoices The corresponding values (as an integer array)
|
||||
wxChoice * ShuttleGuiBase::TieChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & TranslatedChoices)
|
||||
const std::vector<int> & InternalChoices)
|
||||
{
|
||||
wxChoice * pChoice=(wxChoice*)NULL;
|
||||
|
||||
@ -1901,13 +1926,34 @@ wxChoice * ShuttleGuiBase::TieChoice(
|
||||
// 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, TranslatedChoices ); // Int to an index.
|
||||
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, TranslatedChoices ); // Index to int
|
||||
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.
|
||||
/// Behaves identically to the previous, but is meant for use when the choices
|
||||
/// are non-exhaustive and there is a companion control for abitrary entry.
|
||||
/// @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::TieNumberAsChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & InternalChoices)
|
||||
{
|
||||
return ShuttleGuiBase::TieChoice(
|
||||
Prompt, SettingName, Default, Choices, InternalChoices );
|
||||
}
|
||||
|
||||
/// Integer specific version of StartRadioButtonGroup.
|
||||
/// All 'TieRadioButton()' enclosed must be ints.
|
||||
void ShuttleGuiBase::StartRadioButtonGroup( const wxString & SettingName, const int iDefaultValue )
|
||||
@ -2391,7 +2437,7 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
|
||||
const wxString &SettingName,
|
||||
const wxString &Default,
|
||||
const wxArrayString &Choices,
|
||||
const wxArrayString & TranslatedChoices )
|
||||
const wxArrayString & InternalChoices )
|
||||
{
|
||||
StartStruct();
|
||||
AddItem( SettingName, "id" );
|
||||
@ -2405,15 +2451,22 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
|
||||
EndArray();
|
||||
EndField();
|
||||
EndStruct();
|
||||
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, TranslatedChoices );
|
||||
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
|
||||
}
|
||||
wxChoice * ShuttleGuiGetDefinition::TieChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & TranslatedChoices)
|
||||
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" );
|
||||
@ -2426,7 +2479,26 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
|
||||
EndArray();
|
||||
EndField();
|
||||
EndStruct();
|
||||
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, TranslatedChoices );
|
||||
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
|
||||
}
|
||||
wxChoice * ShuttleGuiGetDefinition::TieNumberAsChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & InternalChoices)
|
||||
{
|
||||
// Come here for controls that present non-exhaustive choices among some
|
||||
// numbers, with an associated control that allows arbitrary entry of an
|
||||
// "Other..."
|
||||
StartStruct();
|
||||
AddItem( SettingName, "id" );
|
||||
AddItem( Prompt, "prompt" );
|
||||
AddItem( "number", "type" ); // not "enum" !
|
||||
AddItem( Default, "default" );
|
||||
EndStruct();
|
||||
return ShuttleGui::TieNumberAsChoice(
|
||||
Prompt, SettingName, Default, Choices, InternalChoices );
|
||||
}
|
||||
wxTextCtrl * ShuttleGuiGetDefinition::TieTextBox(
|
||||
const wxString &Prompt,
|
||||
|
@ -27,6 +27,9 @@
|
||||
// For ShuttleGuiGetDefinitions.
|
||||
#include "commands/CommandTargets.h"
|
||||
|
||||
class EnumSetting;
|
||||
|
||||
|
||||
const int nMaxNestedSizers = 20;
|
||||
|
||||
enum teShuttleMode
|
||||
@ -209,18 +212,42 @@ public:
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const bool bDefault);
|
||||
|
||||
// This one is defined in terms of the next and not virtual
|
||||
virtual wxChoice *TieChoice(
|
||||
const wxString &Prompt,
|
||||
EnumSetting &enumSetting );
|
||||
|
||||
virtual wxChoice * TieChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const wxString &Default,
|
||||
const wxArrayString &Choices,
|
||||
const wxArrayString & TranslatedChoices );
|
||||
const wxArrayString & 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 wxArrayString & Choices,
|
||||
const std::vector<int> & TranslatedChoices);
|
||||
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 exhaustive because there is
|
||||
// also an associated control that allows entry of a user-specified value
|
||||
// that is arbitrary (within some bounds).
|
||||
// This behaves just like the previous for building dialogs, but the
|
||||
// behavior is different when the call is intercepted for purposes of
|
||||
// emitting scripting information about Preferences.
|
||||
virtual wxChoice * TieNumberAsChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & InternalChoices );
|
||||
|
||||
virtual wxTextCtrl * TieTextBox(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
@ -421,13 +448,23 @@ public:
|
||||
const wxString &SettingName,
|
||||
const wxString &Default,
|
||||
const wxArrayString &Choices,
|
||||
const wxArrayString & TranslatedChoices ) override;
|
||||
const wxArrayString & InternalChoices ) override;
|
||||
|
||||
// An assertion will be violated if this override is reached!
|
||||
wxChoice * TieChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & TranslatedChoices) override;
|
||||
const std::vector<int> & InternalChoices) override;
|
||||
|
||||
wxChoice * TieNumberAsChoice(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
const int Default,
|
||||
const wxArrayString & Choices,
|
||||
const std::vector<int> & InternalChoices) override;
|
||||
|
||||
wxTextCtrl * TieTextBox(
|
||||
const wxString &Prompt,
|
||||
const wxString &SettingName,
|
||||
|
@ -176,6 +176,7 @@ audio tracks.
|
||||
#include "Prefs.h"
|
||||
#include "prefs/GUISettings.h"
|
||||
#include "prefs/SpectrogramSettings.h"
|
||||
#include "prefs/TracksPrefs.h"
|
||||
#include "prefs/WaveformSettings.h"
|
||||
#include "Spectrum.h"
|
||||
#include "ViewInfo.h"
|
||||
@ -3311,7 +3312,7 @@ void TrackArtist::UpdatePrefs()
|
||||
{
|
||||
mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange);
|
||||
mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
|
||||
gPrefs->Read(wxT("/GUI/SampleView"), &mSampleDisplay, 1);
|
||||
mSampleDisplay = TracksPrefs::SampleViewChoice();
|
||||
SetColours(0);
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ class AUDACITY_DLL_API TrackArtist {
|
||||
// Preference values
|
||||
float mdBrange; // "/GUI/EnvdBRange"
|
||||
long mShowClipping; // "/GUI/ShowClipping"
|
||||
int mSampleDisplay; // "/GUI/SampleView"
|
||||
int mSampleDisplay;
|
||||
bool mbShowTrackNameInWaveform; // "/GUI/ShowTrackNameInWaveform"
|
||||
|
||||
int mMarginLeft;
|
||||
|
@ -96,7 +96,7 @@ WaveTrack::WaveTrack(const std::shared_ptr<DirManager> &projDirManager, sampleFo
|
||||
// Force creation always:
|
||||
WaveformSettings &settings = GetIndependentWaveformSettings();
|
||||
|
||||
mDisplay = FindDefaultViewMode();
|
||||
mDisplay = TracksPrefs::ViewModeChoice();
|
||||
if (mDisplay == obsoleteWaveformDBDisplay) {
|
||||
mDisplay = Waveform;
|
||||
settings.scaleType = WaveformSettings::stLogarithmic;
|
||||
@ -254,32 +254,6 @@ void WaveTrack::SetPanFromChannelType()
|
||||
};
|
||||
|
||||
|
||||
//static
|
||||
WaveTrack::WaveTrackDisplay WaveTrack::FindDefaultViewMode()
|
||||
{
|
||||
// PRL: Bugs 1043, 1044
|
||||
// 2.1.1 writes a NEW key for this preference, which got NEW values,
|
||||
// to avoid confusing version 2.1.0 if it reads the preference file afterwards.
|
||||
// Prefer the NEW preference key if it is present
|
||||
|
||||
WaveTrack::WaveTrackDisplay viewMode;
|
||||
gPrefs->Read(wxT("/GUI/DefaultViewModeNew"), &viewMode, -1);
|
||||
|
||||
// Default to the old key only if not, default the value if it's not there either
|
||||
wxASSERT(WaveTrack::MinDisplay >= 0);
|
||||
if (viewMode < 0) {
|
||||
int oldMode;
|
||||
gPrefs->Read(wxT("/GUI/DefaultViewMode"), &oldMode,
|
||||
(int)(WaveTrack::Waveform));
|
||||
viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode);
|
||||
}
|
||||
|
||||
// Now future-proof 2.1.1 against a recurrence of this sort of bug!
|
||||
viewMode = WaveTrack::ValidateWaveTrackDisplay(viewMode);
|
||||
|
||||
return viewMode;
|
||||
}
|
||||
|
||||
// static
|
||||
WaveTrack::WaveTrackDisplay
|
||||
WaveTrack::ConvertLegacyDisplayValue(int oldValue)
|
||||
|
@ -578,9 +578,6 @@ private:
|
||||
kMaxZoom,
|
||||
};
|
||||
|
||||
// Read appropriate value from preferences
|
||||
static WaveTrackDisplay FindDefaultViewMode();
|
||||
|
||||
// Handle remapping of enum values from 2.1.0 and earlier
|
||||
static WaveTrackDisplay ConvertLegacyDisplayValue(int oldValue);
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "ImportPlugin.h"
|
||||
|
||||
#include "../Tags.h"
|
||||
#include "../prefs/QualityPrefs.h"
|
||||
|
||||
#include "../Experimental.h"
|
||||
|
||||
@ -350,8 +351,7 @@ FLACImportFileHandle::FLACImportFileHandle(const wxString & name)
|
||||
mStreamInfoDone(false),
|
||||
mUpdateResult(ProgressResult::Success)
|
||||
{
|
||||
mFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
mFormat = QualityPrefs::SampleFormatChoice();
|
||||
mFile = std::make_unique<MyFLACFile>(this);
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "ImportPlugin.h"
|
||||
#include "../Internat.h"
|
||||
#include "../Tags.h"
|
||||
#include "../prefs/QualityPrefs.h"
|
||||
|
||||
#define DESC _("MP3 files")
|
||||
|
||||
@ -498,8 +499,7 @@ enum mad_flow output_cb(void *_data,
|
||||
if(data->channels.empty()) {
|
||||
data->channels.resize(channels);
|
||||
|
||||
sampleFormat format = (sampleFormat) gPrefs->
|
||||
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
auto format = QualityPrefs::SampleFormatChoice();
|
||||
|
||||
for(auto &channel: data->channels) {
|
||||
channel = data->trackFactory->NewWaveTrack(format, samplerate);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "../Prefs.h"
|
||||
#include "../Internat.h"
|
||||
#include "../Tags.h"
|
||||
#include "../prefs/QualityPrefs.h"
|
||||
|
||||
|
||||
#define DESC _("Ogg Vorbis files")
|
||||
@ -108,8 +109,7 @@ public:
|
||||
mVorbisFile(std::move(vorbisFile))
|
||||
, mStreamUsage{ static_cast<size_t>(mVorbisFile->links) }
|
||||
{
|
||||
mFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
mFormat = QualityPrefs::SampleFormatChoice();
|
||||
|
||||
for (int i = 0; i < mVorbisFile->links; i++)
|
||||
{
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "../ondemand/ODManager.h"
|
||||
#include "../ondemand/ODComputeSummaryTask.h"
|
||||
#include "../prefs/QualityPrefs.h"
|
||||
|
||||
//If OD is enabled, he minimum number of samples a file has to use it.
|
||||
//Otherwise, we use the older PCMAliasBlockFile method since it should be fast enough.
|
||||
@ -204,8 +205,7 @@ PCMImportFileHandle::PCMImportFileHandle(wxString name,
|
||||
// the quality of the original file.
|
||||
//
|
||||
|
||||
mFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
mFormat = QualityPrefs::SampleFormatChoice();
|
||||
|
||||
if (mFormat != floatSample &&
|
||||
sf_subtype_more_than_16_bits(mInfo.format))
|
||||
|
@ -34,6 +34,7 @@ and sample size to help you importing data of an unknown format.
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../UserException.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../prefs/QualityPrefs.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
@ -193,8 +194,7 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
|
||||
// the quality of the original file.
|
||||
//
|
||||
|
||||
format = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
format = QualityPrefs::SampleFormatChoice();
|
||||
|
||||
if (format != floatSample &&
|
||||
sf_subtype_more_than_16_bits(encoding))
|
||||
|
@ -225,8 +225,7 @@ bool ODFlacDecoder::ReadHeader()
|
||||
{
|
||||
mFormat = int16Sample;//start with the smallest and move up in the metadata_callback.
|
||||
//we want to use the native flac type for quick conversion.
|
||||
/* (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);*/
|
||||
/* QualityPrefs::SampleFormatChoice(); */
|
||||
mFile = std::make_unique<ODFLACFile>(this);
|
||||
|
||||
|
||||
|
@ -30,6 +30,70 @@
|
||||
|
||||
#define ID_SAMPLE_RATE_CHOICE 7001
|
||||
|
||||
//////////
|
||||
|
||||
static const IdentInterfaceSymbol choicesFormat[] = {
|
||||
{ wxT("Format16Bit"), XO("16-bit") },
|
||||
{ wxT("Format24Bit"), XO("24-bit") },
|
||||
{ wxT("Format32BitFloat"), XO("32-bit float") }
|
||||
};
|
||||
static const size_t nChoicesFormat = WXSIZEOF( choicesFormat );
|
||||
static const int intChoicesFormat[] = {
|
||||
int16Sample,
|
||||
int24Sample,
|
||||
floatSample
|
||||
};
|
||||
static_assert( nChoicesFormat == WXSIZEOF(intChoicesFormat), "size mismatch" );
|
||||
|
||||
static const size_t defaultChoiceFormat = 2; // floatSample
|
||||
|
||||
static EncodedEnumSetting formatSetting{
|
||||
wxT("/SamplingRate/DefaultProjectSampleFormatChoice"),
|
||||
choicesFormat, nChoicesFormat, defaultChoiceFormat,
|
||||
|
||||
intChoicesFormat,
|
||||
wxT("/SamplingRate/DefaultProjectSampleFormat"),
|
||||
};
|
||||
|
||||
//////////
|
||||
static const IdentInterfaceSymbol choicesDither[] = {
|
||||
{ XO("None") },
|
||||
{ XO("Rectangle") },
|
||||
{ XO("Triangle") },
|
||||
{ XO("Shaped") },
|
||||
};
|
||||
static const size_t nChoicesDither = WXSIZEOF( choicesDither );
|
||||
static const int intChoicesDither[] = {
|
||||
(int) DitherType::none,
|
||||
(int) DitherType::rectangle,
|
||||
(int) DitherType::triangle,
|
||||
(int) DitherType::shaped,
|
||||
};
|
||||
static_assert(
|
||||
nChoicesDither == WXSIZEOF( intChoicesDither ),
|
||||
"size mismatch"
|
||||
);
|
||||
|
||||
static const int defaultFastDither = 0; // none
|
||||
|
||||
static EncodedEnumSetting fastDitherSetting{
|
||||
wxT("Quality/DitherAlgorithmChoice"),
|
||||
choicesDither, nChoicesDither, defaultFastDither,
|
||||
intChoicesDither,
|
||||
wxT("Quality/DitherAlgorithm")
|
||||
};
|
||||
|
||||
static const int defaultBestDither = 3; // shaped
|
||||
|
||||
static EncodedEnumSetting bestDitherSetting{
|
||||
wxT("Quality/HQDitherAlgorithmChoice"),
|
||||
choicesDither, nChoicesDither, defaultBestDither,
|
||||
|
||||
intChoicesDither,
|
||||
wxT("Quality/HQDitherAlgorithm")
|
||||
};
|
||||
|
||||
//////////
|
||||
BEGIN_EVENT_TABLE(QualityPrefs, PrefsPanel)
|
||||
EVT_CHOICE(ID_SAMPLE_RATE_CHOICE, QualityPrefs::OnSampleRateChoice)
|
||||
END_EVENT_TABLE()
|
||||
@ -71,12 +135,6 @@ void QualityPrefs::Populate()
|
||||
/// The corresponding labels are what gets stored.
|
||||
void QualityPrefs::GetNamesAndLabels()
|
||||
{
|
||||
//------------ Dither Names
|
||||
mDitherNames.Add(_("None")); mDitherLabels.push_back(Dither::none);
|
||||
mDitherNames.Add(_("Rectangle")); mDitherLabels.push_back(Dither::rectangle);
|
||||
mDitherNames.Add(_("Triangle")); mDitherLabels.push_back(Dither::triangle);
|
||||
mDitherNames.Add(_("Shaped")); mDitherLabels.push_back(Dither::shaped);
|
||||
|
||||
//------------ Sample Rate Names
|
||||
// JKC: I don't understand the following comment.
|
||||
// Can someone please explain or correct it?
|
||||
@ -101,18 +159,6 @@ void QualityPrefs::GetNamesAndLabels()
|
||||
|
||||
// The label for the 'Other...' case can be any value at all.
|
||||
mSampleRateLabels.push_back(44100); // If chosen, this value will be overwritten
|
||||
|
||||
//------------- Sample Format Names
|
||||
mSampleFormatNames.Add(wxT("16-bit")); mSampleFormatLabels.push_back(int16Sample);
|
||||
mSampleFormatNames.Add(wxT("24-bit")); mSampleFormatLabels.push_back(int24Sample);
|
||||
mSampleFormatNames.Add(wxT("32-bit float")); mSampleFormatLabels.push_back(floatSample);
|
||||
|
||||
//------------- Converter Names
|
||||
int numConverters = Resample::GetNumMethods();
|
||||
for (int i = 0; i < numConverters; i++) {
|
||||
mConverterNames.Add(Resample::GetMethodName(i));
|
||||
mConverterLabels.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
@ -135,7 +181,7 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
// We make sure it uses the ID we want, so that we get changes
|
||||
S.Id(ID_SAMPLE_RATE_CHOICE);
|
||||
// We make sure we have a pointer to it, so that we can drive it.
|
||||
mSampleRates = S.TieChoice( {},
|
||||
mSampleRates = S.TieNumberAsChoice( {},
|
||||
wxT("/SamplingRate/DefaultProjectSampleRate"),
|
||||
AudioIO::GetOptimalSupportedSampleRate(),
|
||||
mSampleRateNames,
|
||||
@ -149,10 +195,7 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.TieChoice(_("Default Sample &Format:"),
|
||||
wxT("/SamplingRate/DefaultProjectSampleFormat"),
|
||||
floatSample,
|
||||
mSampleFormatNames,
|
||||
mSampleFormatLabels);
|
||||
formatSetting);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
@ -163,17 +206,11 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.StartMultiColumn(2, wxEXPAND);
|
||||
{
|
||||
S.TieChoice(_("Sample Rate Con&verter:"),
|
||||
Resample::GetFastMethodKey(),
|
||||
Resample::GetFastMethodDefault(),
|
||||
mConverterNames,
|
||||
mConverterLabels);
|
||||
Resample::FastMethodSetting);
|
||||
|
||||
/* i18n-hint: technical term for randomization to reduce undesirable resampling artifacts */
|
||||
S.TieChoice(_("&Dither:"),
|
||||
wxT("/Quality/DitherAlgorithm"),
|
||||
Dither::none,
|
||||
mDitherNames,
|
||||
mDitherLabels);
|
||||
fastDitherSetting);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
@ -184,17 +221,11 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.StartMultiColumn(2);
|
||||
{
|
||||
S.TieChoice(_("Sample Rate Conver&ter:"),
|
||||
Resample::GetBestMethodKey(),
|
||||
Resample::GetBestMethodDefault(),
|
||||
mConverterNames,
|
||||
mConverterLabels);
|
||||
Resample::BestMethodSetting);
|
||||
|
||||
/* i18n-hint: technical term for randomization to reduce undesirable resampling artifacts */
|
||||
S.TieChoice(_("Dit&her:"),
|
||||
wxT("/Quality/HQDitherAlgorithm"),
|
||||
Dither::shaped,
|
||||
mDitherNames,
|
||||
mDitherLabels);
|
||||
bestDitherSetting);
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
}
|
||||
@ -239,3 +270,19 @@ PrefsPanel *QualityPrefsFactory::operator () (wxWindow *parent, wxWindowID winid
|
||||
wxASSERT(parent); // to justify safenew
|
||||
return safenew QualityPrefs(parent, winid);
|
||||
}
|
||||
|
||||
sampleFormat QualityPrefs::SampleFormatChoice()
|
||||
{
|
||||
return (sampleFormat)formatSetting.ReadInt();
|
||||
}
|
||||
|
||||
DitherType QualityPrefs::FastDitherChoice()
|
||||
{
|
||||
return (DitherType) fastDitherSetting.ReadInt();
|
||||
}
|
||||
|
||||
DitherType QualityPrefs::BestDitherChoice()
|
||||
{
|
||||
return (DitherType) bestDitherSetting.ReadInt();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "PrefsPanel.h"
|
||||
|
||||
class ShuttleGui;
|
||||
enum sampleFormat : unsigned;
|
||||
enum class DitherType : unsigned;
|
||||
|
||||
class QualityPrefs final : public PrefsPanel
|
||||
{
|
||||
@ -33,19 +35,18 @@ class QualityPrefs final : public PrefsPanel
|
||||
wxString HelpPageName() override;
|
||||
void PopulateOrExchange(ShuttleGui & S) override;
|
||||
|
||||
static sampleFormat SampleFormatChoice();
|
||||
|
||||
static DitherType FastDitherChoice();
|
||||
static DitherType BestDitherChoice();
|
||||
|
||||
private:
|
||||
void Populate();
|
||||
void GetNamesAndLabels();
|
||||
void OnSampleRateChoice(wxCommandEvent & e);
|
||||
|
||||
wxArrayString mDitherNames;
|
||||
std::vector<int> mDitherLabels;
|
||||
wxArrayString mSampleRateNames;
|
||||
std::vector<int> mSampleRateLabels;
|
||||
wxArrayString mSampleFormatNames;
|
||||
std::vector<int> mSampleFormatLabels;
|
||||
wxArrayString mConverterNames;
|
||||
std::vector<int> mConverterLabels;
|
||||
|
||||
wxChoice *mSampleRates;
|
||||
wxTextCtrl *mOtherSampleRate;
|
||||
|
@ -45,17 +45,182 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
static const IdentInterfaceSymbol choicesView[] = {
|
||||
{ XO("Waveform") },
|
||||
{ wxT("WaveformDB"), XO("Waveform (dB)") },
|
||||
{ XO("Spectrogram") }
|
||||
};
|
||||
static const int intChoicesView[] = {
|
||||
(int)(WaveTrack::Waveform),
|
||||
(int)(WaveTrack::obsoleteWaveformDBDisplay),
|
||||
(int)(WaveTrack::Spectrum)
|
||||
};
|
||||
static const size_t nChoicesView = WXSIZEOF(choicesView);
|
||||
static_assert( nChoicesView == WXSIZEOF(intChoicesView), "size mismatch" );
|
||||
|
||||
static const size_t defaultChoiceView = 0;
|
||||
|
||||
class TracksViewModeSetting : public EncodedEnumSetting {
|
||||
public:
|
||||
TracksViewModeSetting(
|
||||
const wxString &key,
|
||||
const IdentInterfaceSymbol symbols[], size_t nSymbols,
|
||||
size_t defaultSymbol,
|
||||
|
||||
const int intValues[],
|
||||
const wxString &oldKey
|
||||
)
|
||||
: EncodedEnumSetting{
|
||||
key, symbols, nSymbols, defaultSymbol, intValues, oldKey }
|
||||
{}
|
||||
|
||||
void Migrate( wxString &value ) override
|
||||
{
|
||||
// Special logic for this preference which was twice migrated!
|
||||
|
||||
// First test for the older but not oldest key:
|
||||
EncodedEnumSetting::Migrate(value);
|
||||
if (!value.empty())
|
||||
return;
|
||||
|
||||
// PRL: Bugs 1043, 1044
|
||||
// 2.1.1 writes a NEW key for this preference, which got NEW values,
|
||||
// to avoid confusing version 2.1.0 if it reads the preference file afterwards.
|
||||
// Prefer the NEW preference key if it is present
|
||||
|
||||
int oldMode;
|
||||
gPrefs->Read(wxT("/GUI/DefaultViewMode"), // The very old key
|
||||
&oldMode,
|
||||
(int)(WaveTrack::Waveform));
|
||||
auto viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode);
|
||||
|
||||
// Now future-proof 2.1.1 against a recurrence of this sort of bug!
|
||||
viewMode = WaveTrack::ValidateWaveTrackDisplay(viewMode);
|
||||
|
||||
const_cast<TracksViewModeSetting*>(this)->WriteInt( viewMode );
|
||||
gPrefs->Flush();
|
||||
|
||||
value = mSymbols[ FindInt(viewMode) ].Internal();
|
||||
}
|
||||
};
|
||||
|
||||
static TracksViewModeSetting viewModeSetting{
|
||||
wxT("/GUI/DefaultViewModeChoice"),
|
||||
choicesView, nChoicesView, defaultChoiceView,
|
||||
|
||||
intChoicesView,
|
||||
wxT("/GUI/DefaultViewModeNew")
|
||||
};
|
||||
|
||||
WaveTrack::WaveTrackDisplay TracksPrefs::ViewModeChoice()
|
||||
{
|
||||
return (WaveTrack::WaveTrackDisplay) viewModeSetting.ReadInt();
|
||||
}
|
||||
|
||||
//////////
|
||||
static const IdentInterfaceSymbol choicesSampleDisplay[] = {
|
||||
{ wxT("ConnectDots"), XO("Connect dots") },
|
||||
{ wxT("StemPlot"), XO("Stem plot") }
|
||||
};
|
||||
static const size_t nChoicesSampleDisplay = WXSIZEOF( choicesSampleDisplay );
|
||||
static const int intChoicesSampleDisplay[] = {
|
||||
(int) WaveTrack::LinearInterpolate,
|
||||
(int) WaveTrack::StemPlot
|
||||
};
|
||||
static_assert(
|
||||
nChoicesSampleDisplay == WXSIZEOF(intChoicesSampleDisplay), "size mismatch" );
|
||||
|
||||
static const size_t defaultChoiceSampleDisplay = 1;
|
||||
|
||||
static EncodedEnumSetting sampleDisplaySetting{
|
||||
wxT("/GUI/SampleViewChoice"),
|
||||
choicesSampleDisplay, nChoicesSampleDisplay, defaultChoiceSampleDisplay,
|
||||
|
||||
intChoicesSampleDisplay,
|
||||
wxT("/GUI/SampleView")
|
||||
};
|
||||
|
||||
WaveTrack::SampleDisplay TracksPrefs::SampleViewChoice()
|
||||
{
|
||||
return (WaveTrack::SampleDisplay) sampleDisplaySetting.ReadInt();
|
||||
}
|
||||
|
||||
//////////
|
||||
static const IdentInterfaceSymbol choicesZoom[] = {
|
||||
{ wxT("FitToWidth"), XO("Fit to Width") },
|
||||
{ wxT("ZoomToSelection"), XO("Zoom to Selection") },
|
||||
{ wxT("ZoomDefault"), XO("Zoom Default") },
|
||||
{ XO("Minutes") },
|
||||
{ XO("Seconds") },
|
||||
{ wxT("FifthsOfSeconds"), XO("5ths of Seconds") },
|
||||
{ wxT("TenthsOfSeconds"), XO("10ths of Seconds") },
|
||||
{ wxT("TwentiethsOfSeconds"), XO("20ths of Seconds") },
|
||||
{ wxT("FiftiethsOfSeconds"), XO("50ths of Seconds") },
|
||||
{ wxT("HundredthsOfSeconds"), XO("100ths of Seconds") },
|
||||
{ wxT("FiveHundredthsOfSeconds"), XO("500ths of Seconds") },
|
||||
{ XO("MilliSeconds") },
|
||||
{ XO("Samples") },
|
||||
{ wxT("FourPixelsPerSample"), XO("4 Pixels per Sample") },
|
||||
{ wxT("MaxZoom"), XO("Max Zoom") },
|
||||
};
|
||||
static const size_t nChoicesZoom = WXSIZEOF( choicesZoom );
|
||||
static const int intChoicesZoom[] = {
|
||||
WaveTrack::kZoomToFit,
|
||||
WaveTrack::kZoomToSelection,
|
||||
WaveTrack::kZoomDefault,
|
||||
WaveTrack::kZoomMinutes,
|
||||
WaveTrack::kZoomSeconds,
|
||||
WaveTrack::kZoom5ths,
|
||||
WaveTrack::kZoom10ths,
|
||||
WaveTrack::kZoom20ths,
|
||||
WaveTrack::kZoom50ths,
|
||||
WaveTrack::kZoom100ths,
|
||||
WaveTrack::kZoom500ths,
|
||||
WaveTrack::kZoomMilliSeconds,
|
||||
WaveTrack::kZoomSamples,
|
||||
WaveTrack::kZoom4To1,
|
||||
WaveTrack::kMaxZoom,
|
||||
};
|
||||
static_assert( nChoicesZoom == WXSIZEOF(intChoicesZoom), "size mismatch" );
|
||||
|
||||
static const size_t defaultChoiceZoom1 = 2; // kZoomDefault
|
||||
|
||||
static EncodedEnumSetting zoom1Setting{
|
||||
wxT("/GUI/ZoomPreset1Choice"),
|
||||
choicesZoom, nChoicesZoom, defaultChoiceZoom1,
|
||||
|
||||
intChoicesZoom,
|
||||
wxT("/GUI/ZoomPreset1")
|
||||
};
|
||||
|
||||
static const size_t defaultChoiceZoom2 = 13; // kZoom4To1
|
||||
|
||||
static EncodedEnumSetting zoom2Setting{
|
||||
wxT("/GUI/ZoomPreset2Choice"),
|
||||
choicesZoom, nChoicesZoom, defaultChoiceZoom2,
|
||||
|
||||
intChoicesZoom,
|
||||
wxT("/GUI/ZoomPreset2")
|
||||
};
|
||||
|
||||
WaveTrack::ZoomPresets TracksPrefs::Zoom1Choice()
|
||||
{
|
||||
return (WaveTrack::ZoomPresets) zoom1Setting.ReadInt();
|
||||
}
|
||||
|
||||
WaveTrack::ZoomPresets TracksPrefs::Zoom2Choice()
|
||||
{
|
||||
return (WaveTrack::ZoomPresets) zoom2Setting.ReadInt();
|
||||
}
|
||||
|
||||
//////////
|
||||
TracksPrefs::TracksPrefs(wxWindow * parent, wxWindowID winid)
|
||||
/* i18n-hint: "Tracks" include audio recordings but also other collections of
|
||||
* data associated with a time line, such as sequences of labels, and musical
|
||||
* notes */
|
||||
: PrefsPanel(parent, winid, _("Tracks"))
|
||||
{
|
||||
// Bugs 1043, 1044
|
||||
// First rewrite legacy preferences
|
||||
gPrefs->Write(wxT("/GUI/DefaultViewModeNew"),
|
||||
(int) WaveTrack::FindDefaultViewMode());
|
||||
|
||||
Populate();
|
||||
}
|
||||
|
||||
@ -68,56 +233,9 @@ void TracksPrefs::Populate()
|
||||
// Keep view choices and codes in proper correspondence --
|
||||
// we don't display them by increasing integer values.
|
||||
|
||||
mViewChoices.Add(_("Waveform"));
|
||||
mViewCodes.push_back((int)(WaveTrack::Waveform));
|
||||
|
||||
mViewChoices.Add(_("Waveform (dB)"));
|
||||
mViewCodes.push_back((int)(WaveTrack::obsoleteWaveformDBDisplay));
|
||||
|
||||
mViewChoices.Add(_("Spectrogram"));
|
||||
mViewCodes.push_back(WaveTrack::Spectrum);
|
||||
|
||||
|
||||
// How samples are displayed when zoomed in:
|
||||
|
||||
mSampleDisplayChoices.Add(_("Connect dots"));
|
||||
mSampleDisplayCodes.push_back((int) WaveTrack::LinearInterpolate);
|
||||
|
||||
mSampleDisplayChoices.Add(_("Stem plot"));
|
||||
mSampleDisplayCodes.push_back((int) WaveTrack::StemPlot);
|
||||
|
||||
mZoomChoices.Add( _("Fit to Width") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomToFit );
|
||||
mZoomChoices.Add( _("Zoom to Selection") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomToSelection );
|
||||
mZoomChoices.Add( _("Zoom Default") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomDefault );
|
||||
mZoomChoices.Add( _("Minutes") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomMinutes );
|
||||
mZoomChoices.Add( _("Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomSeconds );
|
||||
mZoomChoices.Add( _("5ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom5ths );
|
||||
mZoomChoices.Add( _("10ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom10ths );
|
||||
mZoomChoices.Add( _("20ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom20ths );
|
||||
mZoomChoices.Add( _("50ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom50ths );
|
||||
mZoomChoices.Add( _("100ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom100ths );
|
||||
mZoomChoices.Add( _("500ths of Seconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom500ths );
|
||||
mZoomChoices.Add( _("MilliSeconds") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomMilliSeconds );
|
||||
mZoomChoices.Add( _("Samples") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoomSamples );
|
||||
mZoomChoices.Add( _("4 Pixels per Sample") );
|
||||
mZoomCodes.push_back( WaveTrack::kZoom4To1 );
|
||||
mZoomChoices.Add( _("Max Zoom") );
|
||||
mZoomCodes.push_back( WaveTrack::kMaxZoom );
|
||||
|
||||
|
||||
|
||||
//------------------------- Main section --------------------
|
||||
// Now construct the GUI itself.
|
||||
@ -153,16 +271,10 @@ void TracksPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.StartMultiColumn(2);
|
||||
{
|
||||
S.TieChoice(_("Default &view mode:"),
|
||||
wxT("/GUI/DefaultViewModeNew"),
|
||||
0,
|
||||
mViewChoices,
|
||||
mViewCodes);
|
||||
viewModeSetting );
|
||||
|
||||
S.TieChoice(_("Display &samples:"),
|
||||
wxT("/GUI/SampleView"),
|
||||
1,
|
||||
mSampleDisplayChoices,
|
||||
mSampleDisplayCodes);
|
||||
sampleDisplaySetting );
|
||||
|
||||
S.TieTextBox(_("Default audio track &name:"),
|
||||
wxT("/GUI/TrackNames/DefaultTrackName"),
|
||||
@ -178,16 +290,10 @@ void TracksPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.StartMultiColumn(4);
|
||||
{
|
||||
S.TieChoice(_("Preset 1:"),
|
||||
wxT("/GUI/ZoomPreset1"),
|
||||
WaveTrack::kZoomDefault,
|
||||
mZoomChoices,
|
||||
mZoomCodes);
|
||||
zoom1Setting );
|
||||
|
||||
S.TieChoice(_("Preset 2:"),
|
||||
wxT("/GUI/ZoomPreset2"),
|
||||
WaveTrack::kZoom4To1,
|
||||
mZoomChoices,
|
||||
mZoomCodes);
|
||||
zoom2Setting );
|
||||
}
|
||||
}
|
||||
S.EndStatic();
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include "PrefsPanel.h"
|
||||
#include "../WaveTrack.h"
|
||||
|
||||
class ShuttleGui;
|
||||
|
||||
@ -36,18 +37,16 @@ class TracksPrefs final : public PrefsPanel
|
||||
|
||||
static wxString GetDefaultAudioTrackNamePreference();
|
||||
|
||||
static WaveTrack::WaveTrackDisplay ViewModeChoice();
|
||||
static WaveTrack::SampleDisplay SampleViewChoice();
|
||||
static WaveTrack::ZoomPresets Zoom1Choice();
|
||||
static WaveTrack::ZoomPresets Zoom2Choice();
|
||||
|
||||
private:
|
||||
void Populate();
|
||||
void PopulateOrExchange(ShuttleGui & S) override;
|
||||
|
||||
static int iPreferencePinned;
|
||||
|
||||
std::vector<int> mViewCodes;
|
||||
wxArrayString mViewChoices;
|
||||
std::vector<int> mSampleDisplayCodes;
|
||||
wxArrayString mSampleDisplayChoices;
|
||||
std::vector<int> mZoomCodes;
|
||||
wxArrayString mZoomChoices;
|
||||
};
|
||||
|
||||
class TracksPrefsFactory final : public PrefsPanelFactory
|
||||
|
Loading…
x
Reference in New Issue
Block a user