Skip to content

Commit

Permalink
common/chainresampler: hide more implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sinamas committed Apr 28, 2013
1 parent 9bd9759 commit 694c76c
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 104 deletions.
70 changes: 39 additions & 31 deletions common/resample/src/chainresampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
{
}

Expand Down Expand Up @@ -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 (buffer_.size() < (bufSz[0] + bufSz[1]) * channels)
buffer_.reset((bufSz[0] + bufSz[1]) * channels);
if (inSize >= bufSize[i & 1])
bufSize[i & 1] = 0;

buffer2_ = bufSz[1] ? buffer_ + bufSz[0] * channels : 0;
if (buffer_.size() < (bufSize[0] + bufSize[1]) * channels)
buffer_.reset((bufSize[0] + bufSize[1]) * channels);

return (maxOut_ = inSz);
buffer2_ = bufSize[1] ? buffer_ + bufSize[0] * channels : 0;
maxOut_ = inSize;
}

void ChainResampler::adjustRate(long const inRate, long const outRate) {
Expand Down Expand Up @@ -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();
}
95 changes: 34 additions & 61 deletions common/resample/src/chainresampler.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,98 +22,73 @@
#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);

List list_;
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,
float rollOffStart, float rollOffWidth, double gain) {
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;
Expand All @@ -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
Expand All @@ -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
17 changes: 5 additions & 12 deletions common/resample/src/resamplerinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_ =
Expand Down

0 comments on commit 694c76c

Please sign in to comment.