1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 09:39:42 +02:00
audacity/src/Resample.cpp
benjamin.drung@gmail.com 277932dccb Remove trailing spaces.
2014-06-03 20:30:19 +00:00

276 lines
7.7 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
Audacity(R) is copyright (c) 1999-2012 Audacity Team.
License: GPL v2. See License.txt.
Resample.cpp
Dominic Mazzoni, Rob Sykes, Vaughan Johnson
******************************************************************//**
\class Resample
\brief Combined interface to libresample, libsamplerate, and libsoxr.
This class abstracts the interface to different resampling libraries:
libresample, written by Dominic Mazzoni based on Resample-1.7
by Julius Smith. LGPL.
libsamplerate, written by Erik de Castro Lopo. GPL. The author
of libsamplerate requests that you not distribute a binary version
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
contiguous in memory, this class doesn't support multiple channels
or some of the other optional features of some of these resamplers.
*//*******************************************************************/
#include "Resample.h"
#if USE_LIBRESAMPLE
#include "libresample.h"
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
{
this->SetMethod(useBestMethod);
mHandle = resample_open(mMethod, dMinFactor, dMaxFactor);
if(mHandle == NULL) {
fprintf(stderr, "libresample doesn't support range of factors %f to %f.\n", dMinFactor, dMaxFactor);
// FIXME: Audacity will hang after this if branch.
return;
}
}
Resample::~Resample()
{
resample_close(mHandle);
mHandle = NULL;
}
int Resample::GetNumMethods() { return 2; }
wxString Resample::GetMethodName(int index)
{
if (index == 1)
return _("High-quality Sinc Interpolation");
return _("Fast Sinc Interpolation");
}
const wxString Resample::GetFastMethodKey()
{
return wxT("/Quality/LibresampleSampleRateConverter");
}
const wxString Resample::GetBestMethodKey()
{
return wxT("/Quality/LibresampleHQSampleRateConverter");
}
int Resample::GetFastMethodDefault() { return 0; }
int Resample::GetBestMethodDefault() { return 1; }
int Resample::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>
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)) {
fprintf(stderr, "libsamplerate supports only resampling factors between 1/SRC_MAX_RATIO and SRC_MAX_RATIO.\n");
// FIXME: 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;
}
Resample::~Resample()
{
src_delete((SRC_STATE *)mHandle);
mHandle = NULL;
}
int Resample::GetNumMethods()
{
int i = 0;
while(src_get_name(i))
i++;
return i;
}
wxString Resample::GetMethodName(int index)
{
return wxString(wxString::FromAscii(src_get_name(index)));
}
const wxString Resample::GetFastMethodKey()
{
return wxT("/Quality/SampleRateConverter");
}
const wxString Resample::GetBestMethodKey()
{
return wxT("/Quality/HQSampleRateConverter");
}
int Resample::GetFastMethodDefault()
{
return SRC_SINC_FASTEST;
}
int Resample::GetBestMethodDefault()
{
return SRC_SINC_BEST_QUALITY;
}
int Resample::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>
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
{
this->SetMethod(useBestMethod);
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);
}
Resample::~Resample()
{
soxr_delete((soxr_t)mHandle);
mHandle = NULL;
}
int Resample::GetNumMethods() { return 4; }
wxString Resample::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 Resample::GetFastMethodKey()
{
return wxT("/Quality/LibsoxrSampleRateConverter");
}
const wxString Resample::GetBestMethodKey()
{
return wxT("/Quality/LibsoxrHQSampleRateConverter");
}
int Resample::GetFastMethodDefault() {return 1;}
int Resample::GetBestMethodDefault() {return 3;}
int Resample::Process(double factor,
float *inBuffer,
int inBufferLen,
bool lastFlag,
int *inBufferUsed,
float *outBuffer,
int outBufferLen)
{
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);
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;
}
#endif