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