diff --git a/src/Resample.cpp b/src/Resample.cpp index 91b77d578..6e1a947a6 100644 --- a/src/Resample.cpp +++ b/src/Resample.cpp @@ -12,8 +12,7 @@ \class Resample \brief Combined interface to libresample, libsamplerate, and libsoxr. - This class abstracts the interface to two different variable-rate - resampling libraries: + This class abstracts the interface to three different resampling libraries: libresample, written by Dominic Mazzoni based on Resample-1.7 by Julius Smith. LGPL. @@ -22,14 +21,12 @@ of libsamplerate requests that you not distribute a binary version of Audacity that links to libsamplerate and also has plug-in support. - Since Audacity always does resampling on mono streams that are - contiguous in memory, this class doesn't support multiple channels - or some of the other optional features of some of these resamplers. - - and the fixed-rate resampling library: - libsoxr, written by Rob Sykes. LGPL. + Since Audacity always does resampling on mono streams that are + contiguous in memory, this class doesn't support multiple channels + or some of the other optional features of some of these resamplers. + *//*******************************************************************/ @@ -48,11 +45,172 @@ // gPrefs->Flush(); //} -// constant-rate resampler(s) -#ifdef USE_LIBSOXR +// constant-rate resamplers +#if USE_LIBRESAMPLE + #include "libresample.h" + + ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor) + : Resample() + { + this->SetMethod(useBestMethod); + mHandle = resample_open(mMethod, dFactor, dFactor); + } + + ConstRateResample::~ConstRateResample() + { + resample_close(mHandle); + mHandle = NULL; + } + + //v Currently unused. + //wxString ConstRateResample::GetResamplingLibraryName() + //{ + // return _("Libresample by Dominic Mazzoni and Julius Smith"); + //} + + int ConstRateResample::GetNumMethods() { return 2; } + + wxString ConstRateResample::GetMethodName(int index) + { + if (index == 1) + return _("High-quality Sinc Interpolation"); + + return _("Fast Sinc Interpolation"); + } + + const wxString ConstRateResample::GetFastMethodKey() + { + return wxT("/Quality/LibresampleSampleRateConverter"); + } + + const wxString ConstRateResample::GetBestMethodKey() + { + return wxT("/Quality/LibresampleHQSampleRateConverter"); + } + + int ConstRateResample::GetFastMethodDefault() {return 0;} + int ConstRateResample::GetBestMethodDefault() {return 1;} + + int ConstRateResample::Process(double factor, + float *inBuffer, + int inBufferLen, + bool lastFlag, + int *inBufferUsed, + float *outBuffer, + int outBufferLen) + { + return resample_process(mHandle, factor, inBuffer, inBufferLen, + (int)lastFlag, inBufferUsed, outBuffer, outBufferLen); + } + +#elif USE_LIBSAMPLERATE + + #include + + ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor) + : Resample() + { + this->SetMethod(useBestMethod); + if (!src_is_valid_ratio (dFactor) || !src_is_valid_ratio (dFactor)) { + 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. + mHandle = NULL; + return; + } + + int err; + SRC_STATE *state = src_new(mMethod, 1, &err); + mHandle = (void *)state; + mShouldReset = false; + mSamplesLeft = 0; + } + + ConstRateResample::~ConstRateResample() + { + src_delete((SRC_STATE *)mHandle); + mHandle = NULL; + } + + //v Currently unused. + //wxString ConstRateResample::GetResamplingLibraryName() + //{ + // return _("Libsamplerate by Erik de Castro Lopo"); + //} + + int ConstRateResample::GetNumMethods() + { + int i = 0; + + while(src_get_name(i)) + i++; + + return i; + } + + wxString ConstRateResample::GetMethodName(int index) + { + return wxString(wxString::FromAscii(src_get_name(index))); + } + + const wxString ConstRateResample::GetFastMethodKey() + { + return wxT("/Quality/SampleRateConverter"); + } + + const wxString ConstRateResample::GetBestMethodKey() + { + return wxT("/Quality/HQSampleRateConverter"); + } + + int ConstRateResample::GetFastMethodDefault() + { + return SRC_SINC_FASTEST; + } + + int ConstRateResample::GetBestMethodDefault() + { + return SRC_SINC_BEST_QUALITY; + } + + int ConstRateResample::Process(double factor, + float *inBuffer, + int inBufferLen, + bool lastFlag, + int *inBufferUsed, + float *outBuffer, + int outBufferLen) + { + if (mInitial) { + src_set_ratio((SRC_STATE *)mHandle, factor); + mInitial = false; + } + + SRC_DATA data; + + data.data_in = inBuffer; + data.data_out = outBuffer; + data.input_frames = inBufferLen; + data.output_frames = outBufferLen; + data.input_frames_used = 0; + data.output_frames_gen = 0; + data.end_of_input = (int)lastFlag; + data.src_ratio = factor; + + int err = src_process((SRC_STATE *)mHandle, &data); + if (err) { + wxFprintf(stderr, _("Libsamplerate error: %d\n"), err); + return 0; + } + + *inBufferUsed = (int)data.input_frames_used; + return (int)data.output_frames_gen; + } + + +#elif USE_LIBSOXR #include - + ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor) : Resample() { diff --git a/src/Resample.h b/src/Resample.h index a888b7b07..10372dbbd 100644 --- a/src/Resample.h +++ b/src/Resample.h @@ -109,8 +109,8 @@ class ConstRateResample : public Resample ConstRateResample(const bool useBestMethod, const double dFactor); virtual ~ConstRateResample(); - // Override base class methods only if we actually have a const-rate library. - #if USE_LIBSOXR + // Override base class methods only if we actually have a sample rate conversion library. + #if USE_LIBRESAMPLE || USE_LIBSAMPLERATE || USE_LIBSOXR static int GetNumMethods(); static wxString GetMethodName(int index); @@ -143,6 +143,8 @@ class ConstRateResample : public Resample else mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault()); }; + private: + bool mInitial; }; class VarRateResample : public Resample @@ -152,7 +154,7 @@ class VarRateResample : public Resample 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. + // Override base class methods only if we actually have a sample rate conversion 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.