common/chainresampler: less template bloat

This commit is contained in:
sinamas 2013-04-28 19:56:31 +02:00
parent 5558b1e461
commit 0f063671be
2 changed files with 43 additions and 45 deletions

View File

@ -76,8 +76,6 @@ void ChainResampler::downinitAddSincResamplers(double ratio,
float const outRate,
CreateSinc const createBigSinc,
CreateSinc const createSmallSinc,
unsigned const bigSincMul,
unsigned const smallSincMul,
double gain)
{
// For high outRate: Start roll-off at 36 kHz continue until outRate Hz,
@ -92,18 +90,18 @@ void ChainResampler::downinitAddSincResamplers(double ratio,
float const midRollOffStartPlusEnd = midRollOffStart + midRollOffEnd;
float const ideal2ChainMidRatio = get2ChainMidRatio(ratio, finalRollOffLen,
midRollOffStartPlusEnd);
int div_2c = int(ratio * smallSincMul / ideal2ChainMidRatio + 0.5f);
double ratio_2c = ratio * smallSincMul / div_2c;
int div_2c = int(ratio * small_sinc_mul / ideal2ChainMidRatio + 0.5f);
double ratio_2c = ratio * small_sinc_mul / div_2c;
float cost_2c = get2ChainCost(ratio, finalRollOffLen, ratio_2c, midRollOffStartPlusEnd);
if (cost_2c < get1ChainCost(ratio, finalRollOffLen)) {
float const ideal3ChainRatio1 = get3ChainRatio1(ratio_2c, finalRollOffLen,
ratio, midRollOffStartPlusEnd);
int const div1_3c = int(ratio * smallSincMul / ideal3ChainRatio1 + 0.5f);
double const ratio1_3c = ratio * smallSincMul / div1_3c;
int const div1_3c = int(ratio * small_sinc_mul / ideal3ChainRatio1 + 0.5f);
double const ratio1_3c = ratio * small_sinc_mul / div1_3c;
float const ideal3ChainRatio2 = get3ChainRatio2(ratio1_3c, finalRollOffLen,
midRollOffStartPlusEnd);
int const div2_3c = int(ratio1_3c * smallSincMul / ideal3ChainRatio2 + 0.5f);
double const ratio2_3c = ratio1_3c * smallSincMul / div2_3c;
int const div2_3c = int(ratio1_3c * small_sinc_mul / ideal3ChainRatio2 + 0.5f);
double const ratio2_3c = ratio1_3c * small_sinc_mul / div2_3c;
if (get3ChainCost(ratio, finalRollOffLen, ratio1_3c,
ratio2_3c, midRollOffStartPlusEnd) < cost_2c) {
list_.push_back(createSmallSinc(div1_3c,
@ -128,13 +126,36 @@ void ChainResampler::downinitAddSincResamplers(double ratio,
float rollOffStart = 0.5f * (1.0f
+ std::max((outRate - 40000.0f) * outPeriod, 0.0f)
- finalRollOffLen) / ratio;
bigSinc_ = createBigSinc(static_cast<int>(bigSincMul * ratio + 0.5),
bigSinc_ = createBigSinc(static_cast<int>(big_sinc_mul * ratio + 0.5),
rollOffStart,
0.5f * finalRollOffLen / ratio,
gain);
list_.push_back(bigSinc_);
}
void ChainResampler::upinit(long const inRate,
long const outRate,
CreateSinc const createSinc) {
double ratio = static_cast<double>(outRate) / inRate;
// Spectral images above 20 kHz assumed inaudible
// this post-polyphase zero stuffing causes some power loss though.
{
int const div = outRate / std::max(inRate, 40000l);
if (div >= 2) {
list_.push_front(new Upsampler<channels>(div));
ratio /= div;
}
}
float const rollOffLen = std::max((inRate - 36000.0f) / inRate, 0.2f);
bigSinc_ = createSinc(static_cast<int>(big_sinc_mul / ratio + 0.5),
0.5f * (1 - rollOffLen),
0.5f * rollOffLen,
1.0);
list_.push_front(bigSinc_); // note: inserted at the front
reallocateBuffer();
}
void ChainResampler::reallocateBuffer() {
std::size_t bufSize[2] = { 0, 0 };
std::size_t inSize = periodSize_;

View File

@ -46,6 +46,8 @@ private:
typedef std::list<SubResampler *> List;
typedef SubResampler * (*CreateSinc)(unsigned div, float rollOffStart,
float rollOffWidth, double gain);
enum { big_sinc_mul = 2048 };
enum { small_sinc_mul = 32 };
List list_;
SubResampler *bigSinc_;
@ -56,8 +58,10 @@ private:
ChainResampler(long inRate, long outRate, std::size_t periodSize);
void downinitAddSincResamplers(double ratio, float outRate,
CreateSinc createBigSinc, CreateSinc createSmallSinc,
unsigned bigSincMul, unsigned smallSincMul, double gain);
CreateSinc createBigSinc,
CreateSinc createSmallSinc,
double gain);
void upinit(long inRate, long outRate, CreateSinc);
void reallocateBuffer();
template<class Sinc>
@ -68,17 +72,15 @@ private:
template<template<unsigned, unsigned> class Sinc>
void downinit(long inRate, long outRate);
template<template<unsigned, unsigned> class Sinc>
void upinit(long inRate, long outRate);
};
template<template<unsigned, unsigned> class Sinc>
Resampler * ChainResampler::create(long inRate, long outRate, std::size_t periodSize) {
transfer_ptr<ChainResampler> r(new ChainResampler(inRate, outRate, periodSize));
if (outRate > inRate)
r->upinit<Sinc>(inRate, outRate);
else
if (outRate > inRate) {
r->upinit(inRate, outRate,
createSinc< Sinc<channels, big_sinc_mul> >);
} else
r->downinit<Sinc>(inRate, outRate);
return r.release();
@ -87,8 +89,8 @@ Resampler * ChainResampler::create(long inRate, long outRate, std::size_t period
template<template<unsigned, unsigned> class Sinc>
void ChainResampler::downinit(long const inRate,
long const outRate) {
typedef Sinc<channels, 2048> BigSinc;
typedef Sinc<channels, 32> SmallSinc;
typedef Sinc<channels, big_sinc_mul> BigSinc;
typedef Sinc<channels, small_sinc_mul> SmallSinc;
double ratio = static_cast<double>(inRate) / outRate;
double gain = 1.0;
@ -102,32 +104,7 @@ void ChainResampler::downinit(long const inRate,
downinitAddSincResamplers(ratio, outRate,
createSinc<BigSinc>, createSinc<SmallSinc>,
BigSinc::MUL, SmallSinc::MUL, gain);
reallocateBuffer();
}
template<template<unsigned, unsigned> class Sinc>
void ChainResampler::upinit(long const inRate,
long const outRate) {
typedef Sinc<channels, 2048> BigSinc;
typedef Sinc<channels, 32> SmallSinc;
double ratio = static_cast<double>(outRate) / inRate;
// Spectral images above 20 kHz assumed inaudible
// this post-polyphase zero stuffing causes some power loss though.
{
int const div = outRate / std::max(inRate, 40000l);
if (div >= 2) {
list_.push_front(new Upsampler<channels>(div));
ratio /= div;
}
}
float const rollOff = std::max((inRate - 36000.0f) / inRate, 0.2f);
bigSinc_ = new BigSinc(static_cast<int>(BigSinc::MUL / ratio + 0.5),
typename BigSinc::RollOff(0.5f * (1 - rollOff), 0.5f * rollOff),
1.0);
list_.push_front(bigSinc_); // note: inserted at the front
gain);
reallocateBuffer();
}