common/chainresampler: hide more implementation
This commit is contained in:
parent
9bd975961a
commit
694c76c886
@ -17,26 +17,36 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "chainresampler.h"
|
||||
#include "defined_ptr.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
float ChainResampler::get2ChainMidRatio(float ratio, float finalRollOffLen, float midRollOffStartPlusEnd) {
|
||||
static float get1ChainCost(float ratio, float finalRollOffLen) {
|
||||
return ratio / finalRollOffLen;
|
||||
}
|
||||
|
||||
static float get2ChainMidRatio(float ratio, float finalRollOffLen, float midRollOffStartPlusEnd) {
|
||||
return 0.5f * ( std::sqrt(ratio * midRollOffStartPlusEnd * finalRollOffLen)
|
||||
+ midRollOffStartPlusEnd);
|
||||
}
|
||||
|
||||
float ChainResampler::get2ChainCost(float ratio, float finalRollOffLen, float midRatio,
|
||||
float midRollOffStartPlusEnd)
|
||||
static float get2ChainCost(float ratio, float finalRollOffLen, float midRatio,
|
||||
float midRollOffStartPlusEnd)
|
||||
{
|
||||
float midRollOffLen = midRatio * 2 - midRollOffStartPlusEnd;
|
||||
return midRatio * ratio / midRollOffLen
|
||||
+ get1ChainCost(midRatio, finalRollOffLen);
|
||||
}
|
||||
|
||||
float ChainResampler::get3ChainRatio1(float ratio1, float const finalRollOffLen, float const ratio,
|
||||
float const midRollOffStartPlusEnd)
|
||||
static float get3ChainRatio2(float ratio1,
|
||||
float finalRollOffLen,
|
||||
float midRollOffStartPlusEnd) {
|
||||
return get2ChainMidRatio(ratio1, finalRollOffLen, midRollOffStartPlusEnd);
|
||||
}
|
||||
|
||||
static float get3ChainRatio1(float ratio1, float const finalRollOffLen, float const ratio,
|
||||
float const midRollOffStartPlusEnd)
|
||||
{
|
||||
for (unsigned n = 8; n--;) {
|
||||
for (int n = 8; n--;) {
|
||||
float ratio2 = get3ChainRatio2(ratio1, finalRollOffLen, midRollOffStartPlusEnd);
|
||||
ratio1 = ( std::sqrt(ratio * midRollOffStartPlusEnd * (2 - midRollOffStartPlusEnd / ratio2))
|
||||
+ midRollOffStartPlusEnd) * 0.5f;
|
||||
@ -45,16 +55,20 @@ float ChainResampler::get3ChainRatio1(float ratio1, float const finalRollOffLen,
|
||||
return ratio1;
|
||||
}
|
||||
|
||||
float ChainResampler::get3ChainCost(float ratio, float finalRollOffLen,
|
||||
float ratio1, float ratio2, float midRollOffStartPlusEnd)
|
||||
static float get3ChainCost(float ratio, float finalRollOffLen,
|
||||
float ratio1, float ratio2, float midRollOffStartPlusEnd)
|
||||
{
|
||||
float firstRollOffLen = ratio1 * 2 - midRollOffStartPlusEnd;
|
||||
return ratio1 * ratio / firstRollOffLen
|
||||
+ get2ChainCost(ratio1, finalRollOffLen, ratio2, midRollOffStartPlusEnd);
|
||||
}
|
||||
|
||||
ChainResampler::ChainResampler()
|
||||
: bigSinc_(0), buffer2_(0), periodSize_(0)
|
||||
ChainResampler::ChainResampler(long inRate, long outRate, std::size_t periodSize)
|
||||
: Resampler(inRate, outRate)
|
||||
, bigSinc_(0)
|
||||
, buffer2_(0)
|
||||
, periodSize_(periodSize)
|
||||
, maxOut_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -121,26 +135,25 @@ void ChainResampler::downinitAddSincResamplers(double ratio,
|
||||
list_.push_back(bigSinc_);
|
||||
}
|
||||
|
||||
std::size_t ChainResampler::reallocateBuffer() {
|
||||
std::size_t bufSz[2] = { 0, 0 };
|
||||
std::size_t inSz = periodSize_;
|
||||
void ChainResampler::reallocateBuffer() {
|
||||
std::size_t bufSize[2] = { 0, 0 };
|
||||
std::size_t inSize = periodSize_;
|
||||
int i = -1;
|
||||
for (List::iterator it = list_.begin(); it != list_.end(); ++it) {
|
||||
inSz = (inSz * (*it)->mul() - 1) / (*it)->div() + 1;
|
||||
inSize = (inSize * (*it)->mul() - 1) / (*it)->div() + 1;
|
||||
++i;
|
||||
if (inSz > bufSz[i & 1])
|
||||
bufSz[i & 1] = inSz;
|
||||
if (inSize > bufSize[i & 1])
|
||||
bufSize[i & 1] = inSize;
|
||||
}
|
||||
|
||||
if (inSz >= bufSz[i & 1])
|
||||
bufSz[i & 1] = 0;
|
||||
if (inSize >= bufSize[i & 1])
|
||||
bufSize[i & 1] = 0;
|
||||
|
||||
if (buffer_.size() < (bufSz[0] + bufSz[1]) * channels)
|
||||
buffer_.reset((bufSz[0] + bufSz[1]) * channels);
|
||||
if (buffer_.size() < (bufSize[0] + bufSize[1]) * channels)
|
||||
buffer_.reset((bufSize[0] + bufSize[1]) * channels);
|
||||
|
||||
buffer2_ = bufSz[1] ? buffer_ + bufSz[0] * channels : 0;
|
||||
|
||||
return (maxOut_ = inSz);
|
||||
buffer2_ = bufSize[1] ? buffer_ + bufSize[0] * channels : 0;
|
||||
maxOut_ = inSize;
|
||||
}
|
||||
|
||||
void ChainResampler::adjustRate(long const inRate, long const outRate) {
|
||||
@ -180,11 +193,6 @@ std::size_t ChainResampler::resample(short *const out, short const *const in, st
|
||||
return inlen;
|
||||
}
|
||||
|
||||
void ChainResampler::uninit() {
|
||||
buffer2_ = 0;
|
||||
buffer_.reset();
|
||||
periodSize_ = 0;
|
||||
bigSinc_ = 0;
|
||||
ChainResampler::~ChainResampler() {
|
||||
std::for_each(list_.begin(), list_.end(), defined_delete<SubResampler>);
|
||||
list_.clear();
|
||||
}
|
||||
|
@ -22,31 +22,28 @@
|
||||
#include "../resampler.h"
|
||||
#include "../resamplerinfo.h"
|
||||
#include "array.h"
|
||||
#include "subresampler.h"
|
||||
#include "transfer_ptr.h"
|
||||
#include "upsampler.h"
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
class SubResampler;
|
||||
|
||||
class ChainResampler : public Resampler {
|
||||
public:
|
||||
enum { channels = ResamplerInfo::channels };
|
||||
|
||||
ChainResampler();
|
||||
virtual ~ChainResampler() { uninit(); }
|
||||
template<template<unsigned, unsigned> class Sinc>
|
||||
static Resampler * create(long inRate, long outRate, std::size_t periodSize);
|
||||
|
||||
virtual ~ChainResampler();
|
||||
virtual void adjustRate(long inRate, long outRate);
|
||||
virtual void exactRatio(unsigned long &mul, unsigned long &div) const;
|
||||
virtual std::size_t maxOut(std::size_t /*inlen*/) const { return maxOut_; }
|
||||
virtual std::size_t resample(short *out, short const *in, std::size_t inlen);
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t init(long inRate, long outRate, std::size_t periodSize);
|
||||
void uninit();
|
||||
|
||||
private:
|
||||
typedef std::list<SubResampler*> List;
|
||||
typedef std::list<SubResampler *> List;
|
||||
typedef SubResampler * (*CreateSinc)(unsigned div, float rollOffStart,
|
||||
float rollOffWidth, double gain);
|
||||
|
||||
@ -54,32 +51,14 @@ private:
|
||||
SubResampler *bigSinc_;
|
||||
Array<short> buffer_;
|
||||
short *buffer2_;
|
||||
std::size_t periodSize_;
|
||||
std::size_t const periodSize_;
|
||||
std::size_t maxOut_;
|
||||
|
||||
static float get1ChainCost(float ratio, float finalRollOffLen) {
|
||||
return ratio / finalRollOffLen;
|
||||
}
|
||||
|
||||
static float get2ChainMidRatio(float ratio, float finalRollOffLen,
|
||||
float midRollOffStartPlusEnd);
|
||||
static float get2ChainCost(float ratio, float finalRollOffLen, float midRatio,
|
||||
float midRollOffStartPlusEnd);
|
||||
|
||||
static float get3ChainRatio2(float ratio1,
|
||||
float finalRollOffLen,
|
||||
float midRollOffStartPlusEnd) {
|
||||
return get2ChainMidRatio(ratio1, finalRollOffLen, midRollOffStartPlusEnd);
|
||||
}
|
||||
|
||||
static float get3ChainRatio1(float ratio1, float finalRollOffLen, float ratio,
|
||||
float midRollOffStartPlusEnd);
|
||||
static float get3ChainCost(float ratio, float finalRollOffLen, float ratio1, float ratio2,
|
||||
float midRollOffStartPlusEnd);
|
||||
|
||||
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);
|
||||
void reallocateBuffer();
|
||||
|
||||
template<class Sinc>
|
||||
static SubResampler * createSinc(unsigned div,
|
||||
@ -87,33 +66,29 @@ private:
|
||||
return new Sinc(div, typename Sinc::RollOff(rollOffStart, rollOffWidth), gain);
|
||||
}
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t downinit(long inRate, long outRate, std::size_t periodSize);
|
||||
template<template<unsigned, unsigned> class Sinc>
|
||||
void downinit(long inRate, long outRate);
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t upinit(long inRate, long outRate, std::size_t periodSize);
|
||||
|
||||
std::size_t reallocateBuffer();
|
||||
template<template<unsigned, unsigned> class Sinc>
|
||||
void upinit(long inRate, long outRate);
|
||||
};
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t ChainResampler::init(long inRate, long outRate, std::size_t periodSize) {
|
||||
setRate(inRate, 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)
|
||||
return upinit<Sinc>(inRate, outRate, periodSize);
|
||||
r->upinit<Sinc>(inRate, outRate);
|
||||
else
|
||||
return downinit<Sinc>(inRate, outRate, periodSize);
|
||||
r->downinit<Sinc>(inRate, outRate);
|
||||
|
||||
return r.release();
|
||||
}
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t ChainResampler::downinit(long const inRate,
|
||||
long const outRate,
|
||||
std::size_t const periodSize) {
|
||||
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;
|
||||
uninit();
|
||||
periodSize_ = periodSize;
|
||||
|
||||
double ratio = static_cast<double>(inRate) / outRate;
|
||||
double gain = 1.0;
|
||||
@ -125,19 +100,17 @@ std::size_t ChainResampler::downinit(long const inRate,
|
||||
gain *= 1.0 / BigSinc::Cic::gain(div);
|
||||
}
|
||||
|
||||
downinitAddSincResamplers(ratio, outRate, createSinc<BigSinc>,
|
||||
createSinc<SmallSinc>, BigSinc::MUL, SmallSinc::MUL, gain);
|
||||
return reallocateBuffer();
|
||||
downinitAddSincResamplers(ratio, outRate,
|
||||
createSinc<BigSinc>, createSinc<SmallSinc>,
|
||||
BigSinc::MUL, SmallSinc::MUL, gain);
|
||||
reallocateBuffer();
|
||||
}
|
||||
|
||||
template<template<unsigned,unsigned> class Sinc>
|
||||
std::size_t ChainResampler::upinit(long const inRate,
|
||||
long const outRate,
|
||||
std::size_t const periodSize) {
|
||||
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;
|
||||
uninit();
|
||||
periodSize_ = periodSize;
|
||||
|
||||
double ratio = static_cast<double>(outRate) / inRate;
|
||||
// Spectral images above 20 kHz assumed inaudible
|
||||
@ -155,7 +128,7 @@ std::size_t ChainResampler::upinit(long const inRate,
|
||||
typename BigSinc::RollOff(0.5f * (1 - rollOff), 0.5f * rollOff),
|
||||
1.0);
|
||||
list_.push_front(bigSinc_); // note: inserted at the front
|
||||
return reallocateBuffer();
|
||||
reallocateBuffer();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,20 +29,13 @@ static Resampler * createLinint(long inRate, long outRate, std::size_t ) {
|
||||
return new Linint<ResamplerInfo::channels>(inRate, outRate);
|
||||
}
|
||||
|
||||
template<template<unsigned, unsigned> class T>
|
||||
static Resampler * createChainResampler(long inRate, long outRate, std::size_t periodSize) {
|
||||
ChainResampler *r = new ChainResampler;
|
||||
r->init<T>(inRate, outRate, periodSize);
|
||||
return r;
|
||||
}
|
||||
|
||||
ResamplerInfo const ResamplerInfo::resamplers_[] = {
|
||||
{ "Fast", createLinint },
|
||||
{ "High quality (polyphase FIR)", createChainResampler<RectSinc> },
|
||||
// { "Hamming windowed sinc (~50 dB SNR)", createChainResampler<HammingSinc> },
|
||||
// { "Blackman windowed sinc (~70 dB SNR)", createChainResampler<BlackmanSinc> },
|
||||
{ "Very high quality (polyphase FIR)", createChainResampler<Kaiser50Sinc> },
|
||||
{ "Highest quality (polyphase FIR)", createChainResampler<Kaiser70Sinc> },
|
||||
{ "High quality (polyphase FIR)", ChainResampler::create<RectSinc> },
|
||||
// { "Hamming windowed sinc (~50 dB SNR)", ChainResampler::create<HammingSinc> },
|
||||
// { "Blackman windowed sinc (~70 dB SNR)", ChainResampler::create<BlackmanSinc> },
|
||||
{ "Very high quality (polyphase FIR)", ChainResampler::create<Kaiser50Sinc> },
|
||||
{ "Highest quality (polyphase FIR)", ChainResampler::create<Kaiser70Sinc> },
|
||||
};
|
||||
|
||||
std::size_t const ResamplerInfo::num_ =
|
||||
|
Loading…
x
Reference in New Issue
Block a user