mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-02 08:59:28 +02:00
Allow a consistent and coherent choice of sample rate conversion library: any one of the three (or none) to be used, on it's own, no mixtures permitted.
This commit is contained in:
parent
2dea45f5b0
commit
848eb2dc15
174
src/Resample.cpp
174
src/Resample.cpp
@ -12,8 +12,7 @@
|
|||||||
\class Resample
|
\class Resample
|
||||||
\brief Combined interface to libresample, libsamplerate, and libsoxr.
|
\brief Combined interface to libresample, libsamplerate, and libsoxr.
|
||||||
|
|
||||||
This class abstracts the interface to two different variable-rate
|
This class abstracts the interface to three different resampling libraries:
|
||||||
resampling libraries:
|
|
||||||
|
|
||||||
libresample, written by Dominic Mazzoni based on Resample-1.7
|
libresample, written by Dominic Mazzoni based on Resample-1.7
|
||||||
by Julius Smith. LGPL.
|
by Julius Smith. LGPL.
|
||||||
@ -22,14 +21,12 @@
|
|||||||
of libsamplerate requests that you not distribute a binary version
|
of libsamplerate requests that you not distribute a binary version
|
||||||
of Audacity that links to libsamplerate and also has plug-in support.
|
of Audacity that links to libsamplerate and also has plug-in support.
|
||||||
|
|
||||||
|
libsoxr, written by Rob Sykes. LGPL.
|
||||||
|
|
||||||
Since Audacity always does resampling on mono streams that are
|
Since Audacity always does resampling on mono streams that are
|
||||||
contiguous in memory, this class doesn't support multiple channels
|
contiguous in memory, this class doesn't support multiple channels
|
||||||
or some of the other optional features of some of these resamplers.
|
or some of the other optional features of some of these resamplers.
|
||||||
|
|
||||||
and the fixed-rate resampling library:
|
|
||||||
|
|
||||||
libsoxr, written by Rob Sykes. LGPL.
|
|
||||||
|
|
||||||
*//*******************************************************************/
|
*//*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@ -48,9 +45,170 @@
|
|||||||
// gPrefs->Flush();
|
// gPrefs->Flush();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// constant-rate resampler(s)
|
// constant-rate resamplers
|
||||||
#ifdef USE_LIBSOXR
|
#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 <samplerate.h>
|
||||||
|
|
||||||
|
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 <soxr.h>
|
#include <soxr.h>
|
||||||
|
|
||||||
ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor)
|
ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor)
|
||||||
|
@ -109,8 +109,8 @@ class ConstRateResample : public Resample
|
|||||||
ConstRateResample(const bool useBestMethod, const double dFactor);
|
ConstRateResample(const bool useBestMethod, const double dFactor);
|
||||||
virtual ~ConstRateResample();
|
virtual ~ConstRateResample();
|
||||||
|
|
||||||
// Override base class methods only if we actually have a const-rate library.
|
// Override base class methods only if we actually have a sample rate conversion library.
|
||||||
#if USE_LIBSOXR
|
#if USE_LIBRESAMPLE || USE_LIBSAMPLERATE || USE_LIBSOXR
|
||||||
static int GetNumMethods();
|
static int GetNumMethods();
|
||||||
static wxString GetMethodName(int index);
|
static wxString GetMethodName(int index);
|
||||||
|
|
||||||
@ -143,6 +143,8 @@ class ConstRateResample : public Resample
|
|||||||
else
|
else
|
||||||
mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault());
|
mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault());
|
||||||
};
|
};
|
||||||
|
private:
|
||||||
|
bool mInitial;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VarRateResample : public Resample
|
class VarRateResample : public Resample
|
||||||
@ -152,7 +154,7 @@ class VarRateResample : public Resample
|
|||||||
VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor);
|
VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor);
|
||||||
virtual ~VarRateResample();
|
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
|
#if USE_LIBRESAMPLE || USE_LIBSAMPLERATE || USE_LIBSOXR
|
||||||
//vvv Note that we're not actually calling any of these Get* methods
|
//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.
|
// for var-rate, as the decision was to not allow QualityPrefs for it.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user