2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
2012-11-03 02:06:07 +00:00
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
Audacity(R) is copyright (c) 1999-2012 Audacity Team.
|
|
|
|
License: GPL v2. See License.txt.
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2012-11-03 02:06:07 +00:00
|
|
|
Resample.cpp
|
|
|
|
Dominic Mazzoni, Rob Sykes, Vaughan Johnson
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2012-11-03 02:06:07 +00:00
|
|
|
******************************************************************//**
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
\class Resample
|
2015-04-16 19:41:41 +00:00
|
|
|
\brief Interface to libsoxr.
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2013-01-18 00:22:01 +00:00
|
|
|
This class abstracts the interface to different resampling libraries:
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2012-11-03 02:06:07 +00:00
|
|
|
libsoxr, written by Rob Sykes. LGPL.
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2013-01-13 22:31:43 +00:00
|
|
|
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.
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
*//*******************************************************************/
|
|
|
|
|
|
|
|
#include "Resample.h"
|
2015-08-31 19:08:03 +00:00
|
|
|
#include "Prefs.h"
|
2017-09-25 18:07:23 +00:00
|
|
|
#include "Internat.h"
|
2018-11-02 15:31:44 +00:00
|
|
|
#include "../include/audacity/ComponentInterface.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-16 19:41:41 +00:00
|
|
|
#include <soxr.h>
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-16 19:41:41 +00:00
|
|
|
Resample::Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor)
|
|
|
|
{
|
|
|
|
this->SetMethod(useBestMethod);
|
|
|
|
soxr_quality_spec_t q_spec;
|
|
|
|
if (dMinFactor == dMaxFactor)
|
2012-11-03 22:51:50 +00:00
|
|
|
{
|
2015-04-16 19:41:41 +00:00
|
|
|
mbWantConstRateResampling = true; // constant rate resampling
|
|
|
|
q_spec = soxr_quality_spec("\0\1\4\6"[mMethod], 0);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
2015-04-16 19:41:41 +00:00
|
|
|
else
|
2012-11-03 22:51:50 +00:00
|
|
|
{
|
2015-04-16 19:41:41 +00:00
|
|
|
mbWantConstRateResampling = false; // variable rate resampling
|
|
|
|
q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
|
2012-11-03 22:51:50 +00:00
|
|
|
}
|
2017-02-25 23:13:05 +00:00
|
|
|
mHandle.reset(soxr_create(1, dMinFactor, 1, 0, 0, &q_spec, 0));
|
2015-04-16 19:41:41 +00:00
|
|
|
}
|
2012-12-21 01:00:15 +00:00
|
|
|
|
2015-04-16 19:41:41 +00:00
|
|
|
Resample::~Resample()
|
|
|
|
{
|
|
|
|
}
|
2012-12-21 01:00:15 +00:00
|
|
|
|
2018-03-25 01:54:09 +00:00
|
|
|
//////////
|
2019-02-23 17:59:20 +00:00
|
|
|
static const std::initializer_list<EnumValueSymbol> methodNames{
|
2018-03-25 01:54:09 +00:00
|
|
|
{ wxT("LowQuality"), XO("Low Quality (Fastest)") },
|
|
|
|
{ wxT("MediumQuality"), XO("Medium Quality") },
|
|
|
|
{ wxT("HighQuality"), XO("High Quality") },
|
|
|
|
{ wxT("BestQuality"), XO("Best Quality (Slowest)") }
|
|
|
|
};
|
2012-12-21 01:00:15 +00:00
|
|
|
|
2019-02-23 17:59:20 +00:00
|
|
|
static auto intChoicesMethod = {
|
2018-03-25 01:54:09 +00:00
|
|
|
0, 1, 2, 3
|
|
|
|
};
|
|
|
|
|
2019-04-03 13:17:16 +00:00
|
|
|
EnumSetting< int > Resample::FastMethodSetting{
|
2019-02-23 17:59:20 +00:00
|
|
|
wxT("/Quality/LibsoxrSampleRateConverterChoice"),
|
|
|
|
methodNames,
|
|
|
|
1, // Medium Quality
|
2018-03-25 01:54:09 +00:00
|
|
|
|
2019-02-23 17:59:20 +00:00
|
|
|
// for migrating old preferences:
|
2018-03-25 01:54:09 +00:00
|
|
|
intChoicesMethod,
|
2019-02-23 17:59:20 +00:00
|
|
|
wxT("/Quality/LibsoxrSampleRateConverter")
|
2018-03-25 01:54:09 +00:00
|
|
|
};
|
|
|
|
|
2019-04-03 13:17:16 +00:00
|
|
|
EnumSetting< int > Resample::BestMethodSetting
|
2015-04-16 19:41:41 +00:00
|
|
|
{
|
2019-02-23 17:59:20 +00:00
|
|
|
wxT("/Quality/LibsoxrHQSampleRateConverterChoice"),
|
|
|
|
methodNames,
|
|
|
|
3, // Best Quality,
|
2013-01-11 00:13:48 +00:00
|
|
|
|
2019-02-23 17:59:20 +00:00
|
|
|
// for migrating old preferences:
|
2018-03-25 01:54:09 +00:00
|
|
|
intChoicesMethod,
|
2019-02-23 17:59:20 +00:00
|
|
|
wxT("/Quality/LibsoxrHQSampleRateConverter")
|
2018-03-25 01:54:09 +00:00
|
|
|
};
|
2013-01-11 00:13:48 +00:00
|
|
|
|
2018-03-25 01:54:09 +00:00
|
|
|
//////////
|
2016-09-05 17:44:23 +00:00
|
|
|
std::pair<size_t, size_t>
|
|
|
|
Resample::Process(double factor,
|
2015-04-16 19:41:41 +00:00
|
|
|
float *inBuffer,
|
2016-09-05 17:44:23 +00:00
|
|
|
size_t inBufferLen,
|
2015-04-16 19:41:41 +00:00
|
|
|
bool lastFlag,
|
|
|
|
float *outBuffer,
|
2016-09-05 17:44:23 +00:00
|
|
|
size_t outBufferLen)
|
2015-04-16 19:41:41 +00:00
|
|
|
{
|
|
|
|
size_t idone, odone;
|
|
|
|
if (mbWantConstRateResampling)
|
2013-01-11 00:13:48 +00:00
|
|
|
{
|
2017-02-25 23:13:05 +00:00
|
|
|
soxr_process(mHandle.get(),
|
2016-09-05 17:44:23 +00:00
|
|
|
inBuffer , (lastFlag? ~inBufferLen : inBufferLen), &idone,
|
|
|
|
outBuffer, outBufferLen, &odone);
|
2013-01-11 00:13:48 +00:00
|
|
|
}
|
2015-04-16 19:41:41 +00:00
|
|
|
else
|
2012-12-21 01:00:15 +00:00
|
|
|
{
|
2017-02-25 23:13:05 +00:00
|
|
|
soxr_set_io_ratio(mHandle.get(), 1/factor, 0);
|
2012-12-21 01:00:15 +00:00
|
|
|
|
2015-04-16 19:41:41 +00:00
|
|
|
inBufferLen = lastFlag? ~inBufferLen : inBufferLen;
|
2017-02-25 23:13:05 +00:00
|
|
|
soxr_process(mHandle.get(),
|
2016-09-05 17:44:23 +00:00
|
|
|
inBuffer , inBufferLen , &idone,
|
|
|
|
outBuffer, outBufferLen, &odone);
|
2012-12-21 01:00:15 +00:00
|
|
|
}
|
2016-09-05 17:44:23 +00:00
|
|
|
return { idone, odone };
|
2015-04-16 19:41:41 +00:00
|
|
|
}
|
2015-08-31 19:08:03 +00:00
|
|
|
|
|
|
|
void Resample::SetMethod(const bool useBestMethod)
|
|
|
|
{
|
|
|
|
if (useBestMethod)
|
2019-04-03 13:17:16 +00:00
|
|
|
mMethod = BestMethodSetting.ReadEnum();
|
2015-08-31 19:08:03 +00:00
|
|
|
else
|
2019-04-03 13:17:16 +00:00
|
|
|
mMethod = FastMethodSetting.ReadEnum();
|
2015-08-31 19:08:03 +00:00
|
|
|
}
|