From a08d0503be79feb258ec2be14c4ba77bdd667c92 Mon Sep 17 00:00:00 2001 From: "v.audacity" Date: Fri, 11 Jan 2013 00:13:48 +0000 Subject: [PATCH] Rearchitect the class hierarchy a little because of a problem Rob Sykes noted to me off-list, where it was using the key and default prefs methods from the base class rather than the descendant, even when those methods were overridden in the descendant. Also re-ordered and clarified several comments. --- src/Resample.cpp | 44 +++++++++++++++++++----- src/Resample.h | 69 ++++++++++++++++++++++++-------------- src/prefs/QualityPrefs.cpp | 8 ++--- 3 files changed, 83 insertions(+), 38 deletions(-) diff --git a/src/Resample.cpp b/src/Resample.cpp index cfd09d0a3..ae5e67c4d 100644 --- a/src/Resample.cpp +++ b/src/Resample.cpp @@ -54,8 +54,9 @@ #include ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor) - : Resample(useBestMethod) + : Resample() { + this->SetMethod(useBestMethod); soxr_quality_spec_t q_spec = soxr_quality_spec("\0\1\4\6"[mMethod], 0); mHandle = (void *)soxr_create(1, dFactor, 1, 0, 0, &q_spec, 0); } @@ -85,12 +86,12 @@ const wxString ConstRateResample::GetFastMethodKey() { - return wxT("/Quality/SampleRateConverter"); + return wxT("/Quality/LibsoxrSampleRateConverter"); } const wxString ConstRateResample::GetBestMethodKey() { - return wxT("/Quality/HQSampleRateConverter"); + return wxT("/Quality/LibsoxrHQSampleRateConverter"); } int ConstRateResample::GetFastMethodDefault() {return 1;} @@ -114,7 +115,7 @@ #else // no const-rate resampler ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor) - : Resample(useBestMethod) + : Resample() { } @@ -130,8 +131,9 @@ #include "libresample.h" VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor) - : Resample(useBestMethod) + : Resample() { + this->SetMethod(useBestMethod); mHandle = resample_open(mMethod, dMinFactor, dMaxFactor); if(mHandle == NULL) { fprintf(stderr, "libresample doesn't support range %f .. %f.\n", dMinFactor, dMaxFactor); @@ -199,8 +201,9 @@ #include VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor) - : Resample(useBestMethod) + : Resample() { + this->SetMethod(useBestMethod); if (!src_is_valid_ratio (dMinFactor) || !src_is_valid_ratio (dMaxFactor)) { fprintf(stderr, "libsamplerate supports only resampling factors between 1/SRC_MAX_RATIO and SRC_MAX_RATIO.\n"); // FIX-ME: Audacity will hang after this if branch. @@ -314,8 +317,9 @@ #include VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor) - : Resample(useBestMethod) + : Resample() { + this->SetMethod(useBestMethod); soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); mHandle = (void *)soxr_create(1, dMinFactor, 1, 0, 0, &q_spec, 0); } @@ -325,6 +329,30 @@ soxr_delete((soxr_t)mHandle); } + int VarRateResample::GetNumMethods() { return 4; } + + wxString VarRateResample::GetMethodName(int index) + { + static char const * const soxr_method_names[] = { + "Low Quality (Fastest)", "Basic Quality", "High Quality", "Best Quality (Slowest)" + }; + + return wxString(wxString::FromAscii(soxr_method_names[index])); + } + + const wxString VarRateResample::GetFastMethodKey() + { + return wxT("/Quality/LibsoxrSampleRateConverter"); + } + + const wxString VarRateResample::GetBestMethodKey() + { + return wxT("/Quality/LibsoxrHQSampleRateConverter"); + } + + int VarRateResample::GetFastMethodDefault() {return 1;} + int VarRateResample::GetBestMethodDefault() {return 3;} + int VarRateResample::Process(double factor, float *inBuffer, int inBufferLen, @@ -346,7 +374,7 @@ #else // no var-rate resampler VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor) - : Resample(useBestMethod) + : Resample() { } diff --git a/src/Resample.h b/src/Resample.h index 5bbc9deb1..8640ab2e4 100644 --- a/src/Resample.h +++ b/src/Resample.h @@ -27,17 +27,9 @@ class Resample /// the fast method. //v (The particular method used was previously set by /// SetFastMethod or SetBestMethod.) - // minFactor and maxFactor - /// specify the range of factors that will be used, if you plan - /// to vary the factor over time. Otherwise set minFactor and - /// maxFactor to the same value for optimized performance. - Resample(const bool useBestMethod) - { - if (useBestMethod) - mMethod = GetBestMethod(); - else - mMethod = GetFastMethod(); - + Resample() + { + mMethod = 0; mHandle = NULL; }; virtual ~Resample() {}; @@ -48,27 +40,17 @@ class Resample // virtual wxString GetResamplingLibraryName() { return _("Resampling disabled."); }; /// Resamplers may have more than one method, offering a - /// tradeoff between speed and quality. This lets you query - /// the various methods available. - static int GetNumMethods() { return 1; }; - static wxString GetMethodName(int WXUNUSED(index)) { return _("Resampling disabled."); }; - + /// tradeoff between speed and quality. /// Audacity identifies two methods out of all of the choices: /// a Fast method intended for real-time audio I/O, and a Best /// method intended for mixing and exporting. //v (These were previously saved - /// in the preferences when you call Set[Best,Fast]Method.) - int GetFastMethod() { return gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault()); }; - int GetBestMethod() { return gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault()); }; - //v Currently unused. + // in the preferences when you call Set[Best,Fast]Method. + // Now done with TieChoice() in QualityPrefs. + // Implemented in descendant classes, for class-specificity.) //static void SetFastMethod(int index); //static void SetBestMethod(int index); - static const wxString GetFastMethodKey() { return wxT("/Quality/DisabledConverter"); }; - static const wxString GetBestMethodKey() { return wxT("/Quality/DisabledConverter"); }; - static int GetFastMethodDefault() { return 0; }; - static int GetBestMethodDefault() { return 0; }; - /** @brief Main processing function. Resamples from the input buffer to the * output buffer. * @@ -144,17 +126,38 @@ class ConstRateResample : public Resample int *inBufferUsed, float *outBuffer, int outBufferLen); + #else + static int GetNumMethods() { return 1; }; + static wxString GetMethodName(int WXUNUSED(index)) { return _("Resampling disabled."); }; + static const wxString GetFastMethodKey() { return wxT("/Quality/DisabledConverter"); }; + static const wxString GetBestMethodKey() { return wxT("/Quality/DisabledConverter"); }; + static int GetFastMethodDefault() { return 0; }; + static int GetBestMethodDefault() { return 0; }; #endif + + protected: + void SetMethod(const bool useBestMethod) + { + if (useBestMethod) + mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault()); + else + mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault()); + }; }; class VarRateResample : public Resample { public: + // dMinFactor and dMaxFactor specify the range of factors for variable-rate resampling. VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor); virtual ~VarRateResample(); // Override base class methods only if we actually have a var-rate library. #if USE_LIBRESAMPLE || USE_LIBSAMPLERATE || USE_LIBSOXR + //vvv Note that we're not actually calling any of these Get* methods + // for var-rate, as the decision was to not allow QualityPrefs for it. + // However the menthods already existed for libresample and libsamplerate, + // so they're now implemented for all, in case we decide to provide prefs. static int GetNumMethods(); static wxString GetMethodName(int index); @@ -170,7 +173,23 @@ class VarRateResample : public Resample int *inBufferUsed, float *outBuffer, int outBufferLen); + #else + static int GetNumMethods() { return 1; }; + static wxString GetMethodName(int WXUNUSED(index)) { return _("Resampling disabled."); }; + static const wxString GetFastMethodKey() { return wxT("/Quality/DisabledConverter"); }; + static const wxString GetBestMethodKey() { return wxT("/Quality/DisabledConverter"); }; + static int GetFastMethodDefault() { return 0; }; + static int GetBestMethodDefault() { return 0; }; #endif + + protected: + void SetMethod(const bool useBestMethod) + { + if (useBestMethod) + mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault()); + else + mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault()); + }; }; #endif // __AUDACITY_RESAMPLE_H__ diff --git a/src/prefs/QualityPrefs.cpp b/src/prefs/QualityPrefs.cpp index 10a42c474..4c044cc8d 100644 --- a/src/prefs/QualityPrefs.cpp +++ b/src/prefs/QualityPrefs.cpp @@ -110,12 +110,10 @@ void QualityPrefs::GetNamesAndLabels() // We used to set and get best/fast method via Resample.cpp. // Need to ensure that preferences strings in Resample.cpp match. // Note that these methods used to be public and static, but are now protected and pure virtual. - // int converterHQ = Resample::GetBestMethod(); - // int converter = Resample::GetFastMethod(); // - //vvvvv Note that we're now using libsoxr for constant-rate resampling - // and either libresample or libsamplerate for variable-rate, - // and currently *not* allowing method choice for variable-rate, + //vvv Note that we're now using libsoxr for constant-rate resampling + // and either libresample, libsamplerate, or libsoxr for variable-rate, + // and currently not allowing prefs method choice for variable-rate, // per discussion on -devel. int numConverters = ConstRateResample::GetNumMethods(); for (int i = 0; i < numConverters; i++) {