mirror of
https://github.com/cookiengineer/audacity
synced 2026-02-06 11:42:17 +01:00
Go back to simpler architecture for Resample class, now that libsoxr is proven for variable rate resampling.
This commit is contained in:
387
src/Resample.cpp
387
src/Resample.cpp
@@ -32,281 +32,11 @@
|
||||
|
||||
#include "Resample.h"
|
||||
|
||||
//v Currently unused.
|
||||
//void Resample::SetFastMethod(int index)
|
||||
//{
|
||||
// gPrefs->Write(GetFastMethodKey(), (long)index);
|
||||
// gPrefs->Flush();
|
||||
//}
|
||||
//
|
||||
//void Resample::SetBestMethod(int index)
|
||||
//{
|
||||
// gPrefs->Write(GetBestMethodKey(), (long)index);
|
||||
// gPrefs->Flush();
|
||||
//}
|
||||
|
||||
// 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);
|
||||
if(mHandle == NULL) {
|
||||
fprintf(stderr, "libresample doesn't support factor %f.\n", dFactor);
|
||||
// FIX-ME: Audacity will hang after this if branch.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
src_set_ratio((SRC_STATE *)mHandle, factor);
|
||||
|
||||
if(mShouldReset) {
|
||||
if(inBufferLen > mSamplesLeft) {
|
||||
mShouldReset = false;
|
||||
src_reset((SRC_STATE *)mHandle);
|
||||
} else {
|
||||
mSamplesLeft -= inBufferLen;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(lastFlag) {
|
||||
mShouldReset = true;
|
||||
mSamplesLeft = inBufferLen - (int)data.input_frames_used;
|
||||
}
|
||||
|
||||
*inBufferUsed = (int)data.input_frames_used;
|
||||
return (int)data.output_frames_gen;
|
||||
}
|
||||
|
||||
#elif USE_LIBSOXR
|
||||
|
||||
#include <soxr.h>
|
||||
|
||||
ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor)
|
||||
: 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);
|
||||
}
|
||||
|
||||
ConstRateResample::~ConstRateResample()
|
||||
{
|
||||
soxr_delete((soxr_t)mHandle);
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
//v Currently unused.
|
||||
//wxString ConstRateResample::GetResamplingLibraryName()
|
||||
//{
|
||||
// return _("Libsoxr by Rob Sykes");
|
||||
//}
|
||||
|
||||
int ConstRateResample::GetNumMethods() { return 4; }
|
||||
|
||||
wxString ConstRateResample::GetMethodName(int index)
|
||||
{
|
||||
static char const * const soxr_method_names[] = {
|
||||
"Low Quality (Fastest)", "Medium Quality", "High Quality", "Best Quality (Slowest)"
|
||||
};
|
||||
|
||||
return wxString(wxString::FromAscii(soxr_method_names[index]));
|
||||
}
|
||||
|
||||
const wxString ConstRateResample::GetFastMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrSampleRateConverter");
|
||||
}
|
||||
|
||||
const wxString ConstRateResample::GetBestMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrHQSampleRateConverter");
|
||||
}
|
||||
|
||||
int ConstRateResample::GetFastMethodDefault() {return 1;}
|
||||
int ConstRateResample::GetBestMethodDefault() {return 3;}
|
||||
|
||||
int ConstRateResample::Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
int *inBufferUsed,
|
||||
float *outBuffer,
|
||||
int outBufferLen)
|
||||
{
|
||||
size_t idone , odone;
|
||||
soxr_process((soxr_t)mHandle,
|
||||
inBuffer , (size_t)(lastFlag? ~inBufferLen : inBufferLen), &idone,
|
||||
outBuffer, (size_t) outBufferLen, &odone);
|
||||
*inBufferUsed = (int)idone;
|
||||
return (int)odone;
|
||||
}
|
||||
|
||||
#else // no const-rate resampler
|
||||
ConstRateResample::ConstRateResample(const bool useBestMethod, const double dFactor)
|
||||
: Resample()
|
||||
{
|
||||
}
|
||||
|
||||
ConstRateResample::~ConstRateResample()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// variable-rate resamplers
|
||||
#if USE_LIBRESAMPLE
|
||||
|
||||
#include "libresample.h"
|
||||
|
||||
VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
: Resample()
|
||||
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
{
|
||||
this->SetMethod(useBestMethod);
|
||||
mHandle = resample_open(mMethod, dMinFactor, dMaxFactor);
|
||||
@@ -317,21 +47,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
VarRateResample::~VarRateResample()
|
||||
Resample::~Resample()
|
||||
{
|
||||
resample_close(mHandle);
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
//v Currently unused.
|
||||
//wxString VarRateResample::GetResamplingLibraryName()
|
||||
//{
|
||||
// return _("Libresample by Dominic Mazzoni and Julius Smith");
|
||||
//}
|
||||
int Resample::GetNumMethods() { return 2; }
|
||||
|
||||
int VarRateResample::GetNumMethods() { return 2; }
|
||||
|
||||
wxString VarRateResample::GetMethodName(int index)
|
||||
wxString Resample::GetMethodName(int index)
|
||||
{
|
||||
if (index == 1)
|
||||
return _("High-quality Sinc Interpolation");
|
||||
@@ -339,20 +63,20 @@
|
||||
return _("Fast Sinc Interpolation");
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetFastMethodKey()
|
||||
const wxString Resample::GetFastMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibresampleSampleRateConverter");
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetBestMethodKey()
|
||||
const wxString Resample::GetBestMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibresampleHQSampleRateConverter");
|
||||
}
|
||||
|
||||
int VarRateResample::GetFastMethodDefault() { return 0; }
|
||||
int VarRateResample::GetBestMethodDefault() { return 1; }
|
||||
int Resample::GetFastMethodDefault() { return 0; }
|
||||
int Resample::GetBestMethodDefault() { return 1; }
|
||||
|
||||
int VarRateResample::Process(double factor,
|
||||
int Resample::Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
@@ -368,8 +92,7 @@
|
||||
|
||||
#include <samplerate.h>
|
||||
|
||||
VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
: Resample()
|
||||
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
{
|
||||
this->SetMethod(useBestMethod);
|
||||
if (!src_is_valid_ratio (dMinFactor) || !src_is_valid_ratio (dMaxFactor)) {
|
||||
@@ -386,19 +109,13 @@
|
||||
mSamplesLeft = 0;
|
||||
}
|
||||
|
||||
VarRateResample::~VarRateResample()
|
||||
Resample::~Resample()
|
||||
{
|
||||
src_delete((SRC_STATE *)mHandle);
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
//v Currently unused.
|
||||
//wxString Resample::GetResamplingLibraryName()
|
||||
//{
|
||||
// return _("Libsamplerate by Erik de Castro Lopo");
|
||||
//}
|
||||
|
||||
int VarRateResample::GetNumMethods()
|
||||
int Resample::GetNumMethods()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -408,32 +125,32 @@
|
||||
return i;
|
||||
}
|
||||
|
||||
wxString VarRateResample::GetMethodName(int index)
|
||||
wxString Resample::GetMethodName(int index)
|
||||
{
|
||||
return wxString(wxString::FromAscii(src_get_name(index)));
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetFastMethodKey()
|
||||
const wxString Resample::GetFastMethodKey()
|
||||
{
|
||||
return wxT("/Quality/SampleRateConverter");
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetBestMethodKey()
|
||||
const wxString Resample::GetBestMethodKey()
|
||||
{
|
||||
return wxT("/Quality/HQSampleRateConverter");
|
||||
}
|
||||
|
||||
int VarRateResample::GetFastMethodDefault()
|
||||
int Resample::GetFastMethodDefault()
|
||||
{
|
||||
return SRC_SINC_FASTEST;
|
||||
}
|
||||
|
||||
int VarRateResample::GetBestMethodDefault()
|
||||
int Resample::GetBestMethodDefault()
|
||||
{
|
||||
return SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
|
||||
int VarRateResample::Process(double factor,
|
||||
int Resample::Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
@@ -443,8 +160,6 @@
|
||||
{
|
||||
src_set_ratio((SRC_STATE *)mHandle, factor);
|
||||
|
||||
SRC_DATA data;
|
||||
|
||||
if(mShouldReset) {
|
||||
if(inBufferLen > mSamplesLeft) {
|
||||
mShouldReset = false;
|
||||
@@ -454,6 +169,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
SRC_DATA data;
|
||||
data.data_in = inBuffer;
|
||||
data.data_out = outBuffer;
|
||||
data.input_frames = inBufferLen;
|
||||
@@ -479,29 +195,35 @@
|
||||
}
|
||||
|
||||
#elif USE_LIBSOXR
|
||||
// Note that as we currently do not distinguish USE_* flags for var-rate vs const-rate,
|
||||
// we need to have USE_LIBSOXR last in the var-rate #if/#elif implementations, because
|
||||
// it's always #defined in standard configuration, for use as the sole const-rate resampler.
|
||||
|
||||
#include <soxr.h>
|
||||
|
||||
VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
: Resample()
|
||||
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
{
|
||||
this->SetMethod(useBestMethod);
|
||||
soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
|
||||
soxr_quality_spec_t q_spec;
|
||||
if (dMinFactor == dMaxFactor)
|
||||
{
|
||||
mbWantConstRateResampling = true; // constant rate resampling
|
||||
q_spec = soxr_quality_spec("\0\1\4\6"[mMethod], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mbWantConstRateResampling = false; // variable rate resampling
|
||||
q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
|
||||
}
|
||||
mHandle = (void *)soxr_create(1, dMinFactor, 1, 0, 0, &q_spec, 0);
|
||||
}
|
||||
|
||||
VarRateResample::~VarRateResample()
|
||||
Resample::~Resample()
|
||||
{
|
||||
soxr_delete((soxr_t)mHandle);
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
int VarRateResample::GetNumMethods() { return 4; }
|
||||
int Resample::GetNumMethods() { return 4; }
|
||||
|
||||
wxString VarRateResample::GetMethodName(int index)
|
||||
wxString Resample::GetMethodName(int index)
|
||||
{
|
||||
static char const * const soxr_method_names[] = {
|
||||
"Low Quality (Fastest)", "Medium Quality", "High Quality", "Best Quality (Slowest)"
|
||||
@@ -510,20 +232,20 @@
|
||||
return wxString(wxString::FromAscii(soxr_method_names[index]));
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetFastMethodKey()
|
||||
const wxString Resample::GetFastMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrSampleRateConverter");
|
||||
}
|
||||
|
||||
const wxString VarRateResample::GetBestMethodKey()
|
||||
const wxString Resample::GetBestMethodKey()
|
||||
{
|
||||
return wxT("/Quality/LibsoxrHQSampleRateConverter");
|
||||
}
|
||||
|
||||
int VarRateResample::GetFastMethodDefault() {return 1;}
|
||||
int VarRateResample::GetBestMethodDefault() {return 3;}
|
||||
int Resample::GetFastMethodDefault() {return 1;}
|
||||
int Resample::GetBestMethodDefault() {return 3;}
|
||||
|
||||
int VarRateResample::Process(double factor,
|
||||
int Resample::Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
@@ -531,24 +253,23 @@
|
||||
float *outBuffer,
|
||||
int outBufferLen)
|
||||
{
|
||||
soxr_set_io_ratio((soxr_t)mHandle, 1/factor, 0);
|
||||
size_t idone, odone;
|
||||
if (mbWantConstRateResampling)
|
||||
{
|
||||
soxr_process((soxr_t)mHandle,
|
||||
inBuffer , (size_t)(lastFlag? ~inBufferLen : inBufferLen), &idone,
|
||||
outBuffer, (size_t) outBufferLen, &odone);
|
||||
}
|
||||
else
|
||||
{
|
||||
soxr_set_io_ratio((soxr_t)mHandle, 1/factor, 0);
|
||||
|
||||
size_t idone , odone;
|
||||
inBufferLen = lastFlag? ~inBufferLen : inBufferLen;
|
||||
soxr_process((soxr_t)mHandle,
|
||||
inBuffer , (size_t)inBufferLen , &idone,
|
||||
outBuffer, (size_t)outBufferLen, &odone);
|
||||
inBufferLen = lastFlag? ~inBufferLen : inBufferLen;
|
||||
soxr_process((soxr_t)mHandle,
|
||||
inBuffer , (size_t)inBufferLen , &idone,
|
||||
outBuffer, (size_t)outBufferLen, &odone);
|
||||
}
|
||||
*inBufferUsed = (int)idone;
|
||||
return (int)odone;
|
||||
}
|
||||
|
||||
#else // no var-rate resampler
|
||||
VarRateResample::VarRateResample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
||||
: Resample()
|
||||
{
|
||||
}
|
||||
|
||||
VarRateResample::~VarRateResample()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user