mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 23:59:37 +02:00
Go back to simpler architecture for Resample class, now that libsoxr is proven for variable rate resampling.
This commit is contained in:
parent
51e0391b7d
commit
030d2450a8
@ -127,13 +127,13 @@ void AboutDialog::CreateCreditsList()
|
||||
AddCredit(wxT("LAME"), roleLibrary);
|
||||
AddCredit(wxT("libmad"), roleLibrary);
|
||||
#if USE_LIBRESAMPLE
|
||||
AddCredit(wxT("libresample"), roleLibrary);
|
||||
AddCredit(wxT("libresample, by Dominic Mazzoni and Julius Smith"), roleLibrary);
|
||||
#endif
|
||||
#if USE_LIBSAMPLERATE
|
||||
AddCredit(wxT("libsamplerate, by Erik de Castro Lopo"), roleLibrary);
|
||||
#endif
|
||||
#if USE_LIBSOXR
|
||||
AddCredit(wxT("libsoxr"), roleLibrary);
|
||||
AddCredit(wxT("libsoxr, by Rob Sykes"), roleLibrary);
|
||||
#endif
|
||||
AddCredit(wxT("libsndfile"), roleLibrary);
|
||||
AddCredit(wxT("Nyquist"), roleLibrary);
|
||||
|
@ -1322,18 +1322,18 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks,
|
||||
}
|
||||
|
||||
mCaptureBuffers = new RingBuffer* [mCaptureTracks.GetCount()];
|
||||
mResample = new ConstRateResample* [mCaptureTracks.GetCount()];
|
||||
mResample = new Resample* [mCaptureTracks.GetCount()];
|
||||
mFactor = sampleRate / mRate;
|
||||
|
||||
// Set everything to zero in case we have to delete these due to a memory exception.
|
||||
memset(mCaptureBuffers, 0, sizeof(RingBuffer*)*mCaptureTracks.GetCount());
|
||||
memset(mResample, 0, sizeof(ConstRateResample*)*mCaptureTracks.GetCount());
|
||||
memset(mResample, 0, sizeof(Resample*)*mCaptureTracks.GetCount());
|
||||
|
||||
for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ )
|
||||
{
|
||||
mCaptureBuffers[i] = new RingBuffer( mCaptureTracks[i]->GetSampleFormat(),
|
||||
captureBufferSize );
|
||||
mResample[i] = new ConstRateResample(true, mFactor);
|
||||
mResample[i] = new Resample(true, mFactor, mFactor); // constant rate resampling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
class AudioIO;
|
||||
class RingBuffer;
|
||||
class Mixer;
|
||||
class ConstRateResample;
|
||||
class Resample;
|
||||
class TimeTrack;
|
||||
class AudioThread;
|
||||
class Meter;
|
||||
@ -474,7 +474,7 @@ private:
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
AudioThread *mMidiThread;
|
||||
#endif
|
||||
ConstRateResample **mResample;
|
||||
Resample **mResample;
|
||||
RingBuffer **mCaptureBuffers;
|
||||
WaveTrackArray mCaptureTracks;
|
||||
RingBuffer **mPlaybackBuffers;
|
||||
|
@ -286,11 +286,12 @@ Mixer::Mixer(int numInputTracks, WaveTrack **inputTracks,
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
double factor = (mRate / mInputTrack[i]->GetRate());
|
||||
if (timeTrack) {
|
||||
mResample[i] = new VarRateResample(highQuality,
|
||||
factor / timeTrack->GetRangeUpper(),
|
||||
factor / timeTrack->GetRangeLower());
|
||||
// variable rate resampling
|
||||
mResample[i] = new Resample(highQuality,
|
||||
factor / timeTrack->GetRangeUpper(),
|
||||
factor / timeTrack->GetRangeLower());
|
||||
} else {
|
||||
mResample[i] = new ConstRateResample(highQuality, factor);
|
||||
mResample[i] = new Resample(highQuality, factor, factor); // constant rate resampling
|
||||
}
|
||||
mSampleQueue[i] = new float[mQueueMaxLen];
|
||||
mQueueStart[i] = 0;
|
||||
|
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
|
||||
|
154
src/Resample.h
154
src/Resample.h
@ -23,33 +23,26 @@
|
||||
class Resample
|
||||
{
|
||||
public:
|
||||
/// The first parameter lets you select either the best method or
|
||||
/// the fast method.
|
||||
//v (The particular method used was previously set by
|
||||
/// SetFastMethod or SetBestMethod.)
|
||||
Resample()
|
||||
{
|
||||
mMethod = 0;
|
||||
mHandle = NULL;
|
||||
};
|
||||
virtual ~Resample() {};
|
||||
|
||||
/// Returns the name of the library used for resampling
|
||||
/// (long format, may include author name and version number).
|
||||
//v Currently unused.
|
||||
// virtual wxString GetResamplingLibraryName() { return _("Resampling disabled."); };
|
||||
|
||||
/// Resamplers may have more than one method, offering a
|
||||
/// 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.
|
||||
// Now done with TieChoice() in QualityPrefs.
|
||||
// Implemented in descendant classes, for class-specificity.)
|
||||
//static void SetFastMethod(int index);
|
||||
//static void SetBestMethod(int index);
|
||||
//
|
||||
/// The first parameter lets you select either the best method or
|
||||
/// the fast method.
|
||||
// dMinFactor and dMaxFactor specify the range of factors for variable-rate resampling.
|
||||
// For constant-rate, pass the same value for both.
|
||||
Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor);
|
||||
virtual ~Resample();
|
||||
|
||||
static int GetNumMethods();
|
||||
static wxString GetMethodName(int index);
|
||||
|
||||
static const wxString GetFastMethodKey();
|
||||
static const wxString GetBestMethodKey();
|
||||
static int GetFastMethodDefault();
|
||||
static int GetBestMethodDefault();
|
||||
|
||||
/** @brief Main processing function. Resamples from the input buffer to the
|
||||
* output buffer.
|
||||
@ -73,25 +66,21 @@ class Resample
|
||||
@param outBufferLen How big outBuffer is.
|
||||
@return Number of output samples created by this call
|
||||
*/
|
||||
virtual int Process(double WXUNUSED(factor),
|
||||
virtual int Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool WXUNUSED(lastFlag),
|
||||
int * WXUNUSED(inBufferUsed),
|
||||
bool lastFlag,
|
||||
int *inBufferUsed,
|
||||
float *outBuffer,
|
||||
int outBufferLen)
|
||||
int outBufferLen);
|
||||
|
||||
protected:
|
||||
void SetMethod(const bool useBestMethod)
|
||||
{
|
||||
// Base class method just copies data with no change.
|
||||
int i;
|
||||
int len = inBufferLen;
|
||||
|
||||
if (len > outBufferLen)
|
||||
len = outBufferLen;
|
||||
|
||||
for(i=0; i<len; i++)
|
||||
outBuffer[i] = inBuffer[i];
|
||||
|
||||
return len;
|
||||
if (useBestMethod)
|
||||
mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault());
|
||||
else
|
||||
mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault());
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -100,96 +89,9 @@ class Resample
|
||||
#if USE_LIBSAMPLERATE
|
||||
bool mShouldReset; // whether the resampler should be reset because lastFlag has been set previously
|
||||
int mSamplesLeft; // number of samples left before a reset is needed
|
||||
#elif USE_LIBSOXR
|
||||
bool mbWantConstRateResampling;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ConstRateResample : public Resample
|
||||
{
|
||||
public:
|
||||
ConstRateResample(const bool useBestMethod, const double dFactor);
|
||||
virtual ~ConstRateResample();
|
||||
|
||||
// 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);
|
||||
|
||||
static const wxString GetFastMethodKey();
|
||||
static const wxString GetBestMethodKey();
|
||||
static int GetFastMethodDefault();
|
||||
static int GetBestMethodDefault();
|
||||
|
||||
virtual int Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
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(GetFastMethodKey(), GetFastMethodDefault());
|
||||
};
|
||||
};
|
||||
|
||||
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 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.
|
||||
// However the methods 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);
|
||||
|
||||
static const wxString GetFastMethodKey();
|
||||
static const wxString GetBestMethodKey();
|
||||
static int GetFastMethodDefault();
|
||||
static int GetBestMethodDefault();
|
||||
|
||||
virtual int Process(double factor,
|
||||
float *inBuffer,
|
||||
int inBufferLen,
|
||||
bool lastFlag,
|
||||
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(GetFastMethodKey(), GetFastMethodDefault());
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __AUDACITY_RESAMPLE_H__
|
||||
|
@ -1526,7 +1526,7 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
|
||||
return true; // Nothing to do
|
||||
|
||||
double factor = (double)rate / (double)mRate;
|
||||
ConstRateResample* resample = new ConstRateResample(true, factor);
|
||||
::Resample* resample = new ::Resample(true, factor, factor); // constant rate resampling
|
||||
|
||||
int bufsize = 65536;
|
||||
float* inBuffer = new float[bufsize];
|
||||
|
@ -214,7 +214,7 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
||||
float * outBuffer = new float[outBufferSize];
|
||||
|
||||
// Set up the resampling stuff for this track.
|
||||
ConstRateResample resample(true, mFactor);
|
||||
Resample resample(true, mFactor, mFactor); // constant rate resampling
|
||||
|
||||
//Go through the track one buffer at a time. samplePos counts which
|
||||
//sample the current buffer starts at.
|
||||
@ -437,7 +437,7 @@ bool ChangeSpeedDialog::TransferDataFromWindow()
|
||||
|
||||
// handler implementations for ChangeSpeedDialog
|
||||
|
||||
void ChangeSpeedDialog::OnText_PercentChange(wxCommandEvent & event)
|
||||
void ChangeSpeedDialog::OnText_PercentChange(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
if (mbLoopDetect)
|
||||
return;
|
||||
@ -457,7 +457,7 @@ void ChangeSpeedDialog::OnText_PercentChange(wxCommandEvent & event)
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSpeedDialog::OnSlider_PercentChange(wxCommandEvent & event)
|
||||
void ChangeSpeedDialog::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
if (mbLoopDetect)
|
||||
return;
|
||||
@ -475,7 +475,7 @@ void ChangeSpeedDialog::OnSlider_PercentChange(wxCommandEvent & event)
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSpeedDialog::OnChoice_FromVinyl(wxCommandEvent & event)
|
||||
void ChangeSpeedDialog::OnChoice_FromVinyl(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
if (mbLoopDetect)
|
||||
return;
|
||||
@ -489,7 +489,7 @@ void ChangeSpeedDialog::OnChoice_FromVinyl(wxCommandEvent & event)
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSpeedDialog::OnChoice_ToVinyl(wxCommandEvent & event)
|
||||
void ChangeSpeedDialog::OnChoice_ToVinyl(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
if (mbLoopDetect)
|
||||
return;
|
||||
|
@ -107,17 +107,9 @@ void QualityPrefs::GetNamesAndLabels()
|
||||
mSampleFormatNames.Add(wxT("32-bit float")); mSampleFormatLabels.Add(floatSample);
|
||||
|
||||
//------------- Converter Names
|
||||
// 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.
|
||||
//
|
||||
//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();
|
||||
int numConverters = Resample::GetNumMethods();
|
||||
for (int i = 0; i < numConverters; i++) {
|
||||
mConverterNames.Add(ConstRateResample::GetMethodName(i));
|
||||
mConverterNames.Add(Resample::GetMethodName(i));
|
||||
mConverterLabels.Add(i);
|
||||
}
|
||||
}
|
||||
@ -173,8 +165,8 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.SetStretchyCol(2);
|
||||
|
||||
S.TieChoice(_("Sample Rate Con&verter:"),
|
||||
ConstRateResample::GetFastMethodKey(),
|
||||
ConstRateResample::GetFastMethodDefault(),
|
||||
Resample::GetFastMethodKey(),
|
||||
Resample::GetFastMethodDefault(),
|
||||
mConverterNames,
|
||||
mConverterLabels),
|
||||
S.SetSizeHints(mConverterNames);
|
||||
@ -195,8 +187,8 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
S.StartMultiColumn(2);
|
||||
{
|
||||
S.TieChoice(_("Sample Rate Conver&ter:"),
|
||||
ConstRateResample::GetBestMethodKey(),
|
||||
ConstRateResample::GetBestMethodDefault(),
|
||||
Resample::GetBestMethodKey(),
|
||||
Resample::GetBestMethodDefault(),
|
||||
mConverterNames,
|
||||
mConverterLabels),
|
||||
S.SetSizeHints(mConverterNames);
|
||||
@ -215,7 +207,7 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
|
||||
/// Enables or disables the Edit box depending on
|
||||
/// whether we selected 'Other...' or not.
|
||||
void QualityPrefs::OnSampleRateChoice(wxCommandEvent & e)
|
||||
void QualityPrefs::OnSampleRateChoice(wxCommandEvent & WXUNUSED(e))
|
||||
{
|
||||
int sel = mSampleRates->GetSelection();
|
||||
mOtherSampleRate->Enable(sel == (int)mSampleRates->GetCount() - 1);
|
||||
|
@ -22,16 +22,13 @@
|
||||
// #define USE_LIBLRDF 1
|
||||
#define USE_LIBMAD 1
|
||||
|
||||
// Resamplers.
|
||||
// Only one of each type of resampler (constant or variable rate) should be defined.
|
||||
// libsoxr is used for constant-rate and var-rate resampling.
|
||||
// libsoxr currently our only const-rate resampler, so should always be #defined.
|
||||
#define USE_LIBSOXR 1
|
||||
|
||||
// Should build only one of libsoxr, libresample, or libsamplerate for variable-rate resampling,
|
||||
// Resamplers:
|
||||
// Exactly one resampler should be defined.
|
||||
// Should build only one of libsoxr, libresample, or libsamplerate for resampling,
|
||||
// but if more than one are defined, priority is libresample over libsamplerate over libsoxr.
|
||||
// We cannot release builds with libsamplerate, due to licensing.
|
||||
// Standard configuration is to have only USE_LIBSOXR #defined.
|
||||
#define USE_LIBSOXR 1
|
||||
#undef USE_LIBRESAMPLE
|
||||
#undef USE_LIBSAMPLERATE
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user