Cleanup more stuff we don't need

This commit is contained in:
twinaphex 2015-02-17 17:45:33 +01:00
parent 281880de9a
commit 440e49b83d
50 changed files with 0 additions and 11023 deletions

View File

@ -1,7 +0,0 @@
#!/bin/sh
echo "cd libgambatte && scons"
(cd libgambatte && scons) || exit
echo "cd gambatte_qt && qmake && make"
(cd gambatte_qt && qmake && make)

View File

@ -1,7 +0,0 @@
#!/bin/sh
echo "cd libgambatte && scons"
(cd libgambatte && scons) || exit
echo "cd gambatte_sdl && scons"
(cd gambatte_sdl && scons)

View File

@ -1,16 +0,0 @@
#!/bin/sh
echo "cd gambatte_qt && make distclean"
(cd gambatte_qt && make distclean)
echo "cd gambatte_sdl && scons -c"
(cd gambatte_sdl && scons -c)
echo "cd libgambatte && scons -c"
(cd libgambatte && scons -c)
echo "rm -f *gambatte*/config.log"
rm -f *gambatte*/config.log
echo "rm -rf *gambatte*/.scon*"
rm -rf *gambatte*/.scon*

View File

@ -1,56 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "adaptivesleep.h"
usec_t AdaptiveSleep::sleepUntil(usec_t base, usec_t inc) {
usec_t now = getusecs();
usec_t diff = now - base;
if (diff >= inc)
return diff - inc;
diff = inc - diff;
if (diff > oversleep + oversleepVar) {
diff -= oversleep + oversleepVar;
usecsleep(diff);
const usec_t ideal = now + diff;
now = getusecs();
{
usec_t curOversleep = now - ideal;
if (negate(curOversleep) < curOversleep)
curOversleep = 0;
oversleepVar = (oversleepVar * 15 + (curOversleep < oversleep ? oversleep - curOversleep : curOversleep - oversleep) + 8) >> 4;
oversleep = (oversleep * 15 + curOversleep + 8) >> 4;
}
noSleep = 60;
} else if (--noSleep == 0) {
noSleep = 60;
oversleep = oversleepVar = 0;
}
while (now - base < inc)
now = getusecs();
return 0;
}

View File

@ -1,34 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef ADAPTIVE_SLEEP_H
#define ADAPTIVE_SLEEP_H
#include "usec.h"
class AdaptiveSleep {
usec_t oversleep;
usec_t oversleepVar;
unsigned noSleep;
public:
AdaptiveSleep() : oversleep(0), oversleepVar(0), noSleep(60) {}
usec_t sleepUntil(usec_t base, usec_t inc);
};
#endif

View File

@ -1,94 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "rateest.h"
#include <cstdlib>
void RateEst::SumQueue::reset() {
q.clear();
samples_ = usecs_ = 0;
}
void RateEst::SumQueue::push(const long samples, const usec_t usecs) {
q.push_back(pair_t(samples, usecs));
samples_ += samples;
usecs_ += usecs;
}
void RateEst::SumQueue::pop() {
const pair_t &f = q.front();
samples_ -= f.first;
usecs_ -= f.second;
q.pop_front();
}
static usec_t sampleUsecs(long samples, long rate) {
return static_cast<usec_t>((samples * 1000000.0f) / (rate ? rate : 1) + 0.5f);
}
static long limit(long est, const long reference) {
if (est > reference + (reference >> 6))
est = reference + (reference >> 6);
else if (est < reference - (reference >> 6))
est = reference - (reference >> 6);
return est;
}
void RateEst::init(long srate, long reference, const long maxSamplePeriod) {
maxPeriod = sampleUsecs(maxSamplePeriod, reference);
srate <<= UPSHIFT;
reference <<= UPSHIFT;
this->srate = limit(srate, reference);
last = 0;
this->reference = reference;
samples = ((this->srate >> UPSHIFT) * 12) << 5;
usecs = 12000000 << 5;
sumq.reset();
}
void RateEst::feed(long samplesIn, const usec_t now) {
usec_t usecsIn = now - last;
if (last && usecsIn < maxPeriod) {
sumq.push(samplesIn, usecsIn);
while ((usecsIn = sumq.usecs()) > 100000) {
samplesIn = sumq.samples();
sumq.pop();
if (std::abs(static_cast<long>(samplesIn * (1000000.0f * UP) / usecsIn) - reference) < reference >> 1) {
samples += (samplesIn - sumq.samples()) << 5;
usecs += (usecsIn - sumq.usecs()) << 5;
long est = static_cast<long>(samples * (1000000.0f * UP) / usecs + 0.5f);
est = limit((srate * 31 + est + 16) >> 5, reference);
srate = est;
if (usecs > 16000000 << 5) {
samples = (samples * 3 + 2) >> 2;
usecs = (usecs * 3 + 2) >> 2;
}
}
}
}
last = now;
}

View File

@ -1,66 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RATEEST_H
#define RATEEST_H
#include "usec.h"
#include <deque>
#include <utility>
class RateEst {
class SumQueue {
typedef std::pair<long, usec_t> pair_t;
typedef std::deque<pair_t> q_t;
q_t q;
long samples_;
usec_t usecs_;
public:
SumQueue() : samples_(0), usecs_(0) {}
void reset();
long samples() const { return samples_; }
usec_t usecs() const { return usecs_; }
void push(long samples, usec_t usecs);
void pop();
};
enum { UPSHIFT = 5 };
enum { UP = 1 << UPSHIFT };
long srate;
SumQueue sumq;
usec_t last;
usec_t usecs;
usec_t maxPeriod;
long reference;
long samples;
public:
RateEst(long srate = 0) { init(srate); }
RateEst(long srate, long reference) { init(srate, reference); }
void init(long srate) { init(srate, srate); }
void init(long srate, long reference) { init(srate, reference, reference); }
void init(long srate, long reference, long maxSamplePeriod);
void reset() { last = 0; }
void feed(long samples, usec_t usecs = getusecs());
long result() const { return (srate + UP / 2) >> UPSHIFT; }
};
#endif

View File

@ -1,73 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RESAMPLER_H
#define RESAMPLER_H
#include <cstddef>
/** Interface to a Resampler. */
class Resampler {
long inRate_;
long outRate_;
protected:
void setRate(const long inRate, const long outRate) { inRate_ = inRate; outRate_ = outRate; }
Resampler() : inRate_(0), outRate_(0) {}
public:
/** Returns the sampling rate of the input that this resampler expects. */
long inRate() const { return inRate_; }
/** Returns the approximate sampling rate of the output. */
long outRate() const { return outRate_; }
/** Can be used to adjust the input and output sampling rates slightly with minimal disturbance in the output.
* Should only be used for slight changes or the quality could detoriate.
* It can for instance be useful to tweak the output rate slightly to synchronize production speed to playback
* speed when synchronizing video frame rate to refresh rate while playing back audio from the same source.
* This can reduce skipped or duplicated video frames (or avoid audio underruns if no frame skipping is done).
*
* @param inRate New input sampling rate.
* @param outRate Desired new output sampling rate.
*/
virtual void adjustRate(long inRate, long outRate) = 0;
/** Returns the exact ratio that this resampler is configured to use,
* such that the actual output sampling rate is (input rate) * mul / div.
* outRate() / inRate() is not necessarily equal to mul / div.
* Many resampler are intended for real-time purposes where it does not matter
* much whether the output sampling rate is 100% exact. Playback hardware is also slightly off.
*/
virtual void exactRatio(unsigned long &mul, unsigned long &div) const = 0;
/** Returns an upper bound on how many samples are produced for 'inlen' input samples.
* Can be used to calculate buffer sizes.
*/
virtual std::size_t maxOut(std::size_t inlen) const = 0;
/** Resamples the samples in 'in' and puts the resulting samples in 'out'.
*
* @param inlen The number of samples in 'in' to be resampled/consumed.
* @return The number of samples produced in 'out'.
*/
virtual std::size_t resample(short *out, const short *in, std::size_t inlen) = 0;
virtual ~Resampler() {}
};
#endif

View File

@ -1,52 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RESAMPLER_INFO_H
#define RESAMPLER_INFO_H
#include "resampler.h"
/** Used for creating instances of resamplers, and getting information on available resamplers.
* Currently creates resamplers that expect stereo samples. All 'numbers of samples' are in
* number of stereo samples. (This can be changed by adjusting the 'channels' enum in src/chainresampler.h
* to the number of desired channels.).
*/
struct ResamplerInfo {
/** Short character string description of the resampler. */
const char *desc;
/** Points to a function that can be used to create an instance of the resampler.
* @param inRate The input sampling rate.
* @param outRate The desired output sampling rate.
* @param periodSz The maximum number of input samples to resample at a time. That is the maximal inlen passed to Resampler::resample.
* @return Pointer to the created instance (on the heap). Caller must free this with the delete operator.
*/
Resampler* (*create)(long inRate, long outRate, std::size_t periodSz);
/** Returns the number of ResamplerInfos that can be gotten with get(). */
static unsigned num() { return num_; }
/** Returns ResamplerInfo number n. Where n is less than num(). */
static const ResamplerInfo& get(unsigned n) { return resamplers[n]; }
private:
static const ResamplerInfo resamplers[];
static const unsigned num_;
};
#endif

View File

@ -1,100 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef BLACKMANSINC_H
#define BLACKMANSINC_H
#include "convoluter.h"
#include "subresampler.h"
#include "makesinckernel.h"
#include "cic4.h"
#include "gambatte-array.h"
#include <cmath>
#include <cstdlib>
template<unsigned channels, unsigned phases>
class BlackmanSinc : public SubResampler {
PolyPhaseConvoluter<channels, phases> convoluters[channels];
Array<short> kernel;
static double blackmanWin(const long i, const long M) {
static const double PI = 3.14159265358979323846;
return 0.42 - 0.5 * std::cos(2 * PI * i / M) + 0.08 * std::cos(4 * PI * i / M);
}
void init(unsigned div, unsigned phaseLen, double fc);
public:
enum { MUL = phases };
typedef Cic4<channels> Cic;
static float cicLimit() { return 4.7f; }
class RollOff {
static unsigned toTaps(const float rollOffWidth) {
static const float widthTimesTaps = 4.5f;
return static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth));
}
static float toFc(const float rollOffStart, const int taps) {
static const float startToFcDeltaTimesTaps = 1.69f;
return startToFcDeltaTimesTaps / taps + rollOffStart;
}
public:
const unsigned taps;
const float fc;
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
};
BlackmanSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); }
BlackmanSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void adjustDiv(unsigned div);
unsigned mul() const { return MUL; }
unsigned div() const { return convoluters[0].div(); }
};
template<unsigned channels, unsigned phases>
void BlackmanSinc<channels, phases>::init(const unsigned div, const unsigned phaseLen, const double fc) {
kernel.reset(phaseLen * phases);
makeSincKernel(kernel, phases, phaseLen, fc, blackmanWin);
for (unsigned i = 0; i < channels; ++i)
convoluters[i].reset(kernel, phaseLen, div);
}
template<unsigned channels, unsigned phases>
std::size_t BlackmanSinc<channels, phases>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i)
samplesOut = convoluters[i].filter(out + i, in + i, inlen);
return samplesOut;
}
template<unsigned channels, unsigned phases>
void BlackmanSinc<channels, phases>::adjustDiv(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
convoluters[i].adjustDiv(div);
}
#endif

View File

@ -1,124 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "chainresampler.h"
float ChainResampler::get2ChainMidRatio(const float ratio, const float finalRollOffLen, const float midRollOffStartPlusEnd) {
return 0.5f * (std::sqrt(ratio * midRollOffStartPlusEnd * finalRollOffLen) + midRollOffStartPlusEnd);
}
float ChainResampler::get2ChainCost(const float ratio, const float finalRollOffLen, const float midRatio, const float midRollOffStartPlusEnd) {
const float midRollOffLen = midRatio * 2 - midRollOffStartPlusEnd;
return midRatio * ratio / midRollOffLen + get1ChainCost(midRatio, finalRollOffLen);
}
float ChainResampler::get3ChainRatio1(float ratio1, const float finalRollOffLen, const float ratio, const float midRollOffStartPlusEnd) {
for (unsigned n = 8; n--;) {
const float ratio2 = get3ChainRatio2(ratio1, finalRollOffLen, midRollOffStartPlusEnd);
ratio1 = 0.5f * (std::sqrt(ratio * midRollOffStartPlusEnd * (2 - midRollOffStartPlusEnd / ratio2)) + midRollOffStartPlusEnd);
}
return ratio1;
}
float ChainResampler::get3ChainCost(const float ratio, const float finalRollOffLen,
const float ratio1, const float ratio2, const float midRollOffStartPlusEnd) {
const float firstRollOffLen = ratio1 * 2 - midRollOffStartPlusEnd;
return ratio1 * ratio / firstRollOffLen + get2ChainCost(ratio1, finalRollOffLen, ratio2, midRollOffStartPlusEnd);
}
ChainResampler::ChainResampler()
: bigSinc(0), buffer2(0), periodSize(0)
{
}
std::size_t ChainResampler::reallocateBuffer() {
std::size_t bufSz[2] = { 0, 0 };
std::size_t inSz = periodSize;
int i = -1;
for (list_t::iterator it = list.begin(); it != list.end(); ++it) {
inSz = (inSz * (*it)->mul() - 1) / (*it)->div() + 1;
++i;
if (inSz > bufSz[i&1])
bufSz[i&1] = inSz;
}
if (inSz >= bufSz[i&1])
bufSz[i&1] = 0;
if (buffer.size() < (bufSz[0] + bufSz[1]) * channels)
buffer.reset((bufSz[0] + bufSz[1]) * channels);
buffer2 = bufSz[1] ? buffer + bufSz[0] * channels : 0;
return (maxOut_ = inSz);
}
void ChainResampler::adjustRate(const long inRate, const long outRate) {
unsigned long mul, div;
exactRatio(mul, div);
bigSinc->adjustDiv(static_cast<int>(static_cast<double>(inRate) * mul / (static_cast<double>(div / bigSinc->div()) * outRate) + 0.5));
reallocateBuffer();
setRate(inRate, outRate);
}
void ChainResampler::exactRatio(unsigned long &mul, unsigned long &div) const {
mul = 1;
div = 1;
for (list_t::const_iterator it = list.begin(); it != list.end(); ++it) {
mul *= (*it)->mul();
div *= (*it)->div();
}
}
std::size_t ChainResampler::resample(short *const out, const short *const in, std::size_t inlen) {
assert(inlen <= periodSize);
short *const buf = buffer != buffer2 ? buffer : out;
short *const buf2 = buffer2 ? buffer2 : out;
const short *inbuf = in;
short *outbuf = 0;
for (list_t::iterator it = list.begin(); it != list.end(); ++it) {
outbuf = ++list_t::iterator(it) == list.end() ? out : (inbuf == buf ? buf2 : buf);
inlen = (*it)->resample(outbuf, inbuf, inlen);
inbuf = outbuf;
}
return inlen;
}
void ChainResampler::uninit() {
buffer2 = 0;
buffer.reset();
periodSize = 0;
bigSinc = 0;
for (list_t::iterator it = list.begin(); it != list.end(); ++it)
delete *it;
list.clear();
}

View File

@ -1,196 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CHAINRESAMPLER_H
#define CHAINRESAMPLER_H
#include <cmath>
#include <cstdlib>
#include <cassert>
#include <cstddef>
#include <list>
#include "gambatte-array.h"
#include "subresampler.h"
#include "../resampler.h"
#include "upsampler.h"
class ChainResampler : public Resampler {
typedef std::list<SubResampler*> list_t;
list_t list;
SubResampler *bigSinc;
Array<short> buffer;
short *buffer2;
std::size_t 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);
template<template<unsigned,unsigned> class Sinc>
std::size_t downinit(long inRate, long outRate, std::size_t periodSize);
template<template<unsigned,unsigned> class Sinc>
std::size_t upinit(long inRate, long outRate, std::size_t periodSize);
std::size_t reallocateBuffer();
public:
enum { channels = 2 };
ChainResampler();
~ChainResampler() { uninit(); }
void adjustRate(long inRate, long outRate);
void exactRatio(unsigned long &mul, unsigned long &div) const;
template<template<unsigned,unsigned> class Sinc>
std::size_t init(long inRate, long outRate, std::size_t periodSize);
std::size_t maxOut(std::size_t /*inlen*/) const { return maxOut_; }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void uninit();
};
template<template<unsigned,unsigned> class Sinc>
std::size_t ChainResampler::init(const long inRate, const long outRate, const std::size_t periodSize) {
setRate(inRate, outRate);
if (outRate > inRate)
return upinit<Sinc>(inRate, outRate, periodSize);
else
return downinit<Sinc>(inRate, outRate, periodSize);
}
template<template<unsigned,unsigned> class Sinc>
std::size_t ChainResampler::downinit(const long inRate, const long outRate, const std::size_t periodSize) {
typedef Sinc<channels,2048> BigSinc;
typedef Sinc<channels,32> SmallSinc;
uninit();
this->periodSize = periodSize;
double ratio = static_cast<double>(inRate) / outRate;
while (ratio >= BigSinc::cicLimit() * 2) {
const int div = std::min<int>(static_cast<int>(ratio / BigSinc::cicLimit()), BigSinc::Cic::MAX_DIV);
list.push_back(new typename BigSinc::Cic(div));
ratio /= div;
}
// For high outRate: Start roll-off at 36000 Hz continue until outRate Hz, then wrap around back down to 40000 Hz.
const float outPeriod = 1.0f / outRate;
const float finalRollOffLen = std::max((outRate - 36000.0f + outRate - 40000.0f) * outPeriod, 0.2f);
{
const float midRollOffStart = std::min(36000.0f * outPeriod, 1.0f);
const float midRollOffEnd = std::min(40000.0f * outPeriod, 1.0f); // after wrap at folding freq.
const float midRollOffStartPlusEnd = midRollOffStart + midRollOffEnd;
int div_2c = static_cast<int>(ratio * SmallSinc::MUL / get2ChainMidRatio(ratio, finalRollOffLen, midRollOffStartPlusEnd) + 0.5f);
double ratio_2c = ratio * SmallSinc::MUL / div_2c;
float cost_2c = get2ChainCost(ratio, finalRollOffLen, ratio_2c, midRollOffStartPlusEnd);
if (cost_2c < get1ChainCost(ratio, finalRollOffLen)) {
const int div1_3c = static_cast<int>(
ratio * SmallSinc::MUL / get3ChainRatio1(ratio_2c, finalRollOffLen, ratio, midRollOffStartPlusEnd) + 0.5f);
const double ratio1_3c = ratio * SmallSinc::MUL / div1_3c;
const int div2_3c = static_cast<int>(
ratio1_3c * SmallSinc::MUL / get3ChainRatio2(ratio1_3c, finalRollOffLen, midRollOffStartPlusEnd) + 0.5f);
const double ratio2_3c = ratio1_3c * SmallSinc::MUL / div2_3c;
if (get3ChainCost(ratio, finalRollOffLen, ratio1_3c, ratio2_3c, midRollOffStartPlusEnd) < cost_2c) {
list.push_back(new SmallSinc(div1_3c, typename SmallSinc::RollOff(
0.5f * midRollOffStart / ratio, (ratio1_3c - 0.5f * midRollOffStartPlusEnd) / ratio)));
ratio = ratio1_3c;
div_2c = div2_3c;
ratio_2c = ratio2_3c;
}
list.push_back(new SmallSinc(div_2c, typename SmallSinc::RollOff(
0.5f * midRollOffStart / ratio, (ratio_2c - 0.5f * midRollOffStartPlusEnd) / ratio)));
ratio = ratio_2c;
}
}
list.push_back(bigSinc = new BigSinc(static_cast<int>(BigSinc::MUL * ratio + 0.5), typename BigSinc::RollOff(
0.5f * (1.0f + std::max((outRate - 40000.0f) * outPeriod, 0.0f) - finalRollOffLen) / ratio, 0.5f * finalRollOffLen / ratio)));
return reallocateBuffer();
}
template<template<unsigned,unsigned> class Sinc>
std::size_t ChainResampler::upinit(const long inRate, const long outRate, const std::size_t periodSize) {
typedef Sinc<channels,2048> BigSinc;
typedef Sinc<channels,32> SmallSinc;
uninit();
this->periodSize = periodSize;
double ratio = static_cast<double>(outRate) / inRate;
// Spectral images above 20 kHz assumed inaudible
{
const int div = outRate / std::max(inRate, 40000l);
if (div >= 2) {
list.push_front(new Upsampler<channels>(div));
ratio /= div;
}
}
const float rollOff = std::max((inRate - 36000.0f) / inRate, 0.2f);
/*{
int div_2c = get2ChainMidRatio(ratio, rollOff) * SmallSinc::MUL / ratio + 0.5f;
double ratio_2c = ratio * div_2c / SmallSinc::MUL;
float cost_2c = get2ChainCost(ratio, rollOff, ratio_2c);
if (cost_2c < get1ChainCost(ratio, rollOff)) {
const int div1_3c = get3ChainRatio1(ratio_2c, rollOff, ratio) * SmallSinc::MUL / ratio + 0.5f;
const double ratio1_3c = ratio * div1_3c / SmallSinc::MUL;
const int div2_3c = get3ChainRatio2(ratio1_3c, rollOff) * SmallSinc::MUL / ratio1_3c + 0.5f;
const double ratio2_3c = ratio1_3c * div2_3c / SmallSinc::MUL;
if (get3ChainCost(ratio, rollOff, ratio1_3c, ratio2_3c) < cost_2c) {
list.push_front(new SmallSinc(div1_3c, typename SmallSinc::RollOff(0.5f / ratio1_3c, (ratio1_3c - 1) / ratio1_3c)));
ratio = ratio1_3c;
div_2c = div2_3c;
ratio_2c = ratio2_3c;
}
list.push_front(new SmallSinc(div_2c, typename SmallSinc::RollOff(0.5f / ratio_2c, (ratio_2c - 1) / ratio_2c)));
ratio = ratio_2c;
}
}*/
list.push_front(bigSinc = new BigSinc(
static_cast<int>(BigSinc::MUL / ratio + 0.5), typename BigSinc::RollOff(0.5f * (1 - rollOff), 0.5f * rollOff)));
return reallocateBuffer();
}
#endif

View File

@ -1,242 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CIC2_H
#define CIC2_H
#include "subresampler.h"
#include "rshift16_round.h"
template<unsigned channels>
class Cic2Core {
// enum { BUFLEN = 64 };
// unsigned long buf[BUFLEN];
unsigned long sum1;
unsigned long sum2;
unsigned long prev1;
// unsigned long prev2;
unsigned div_;
unsigned nextdivn;
// unsigned bufpos;
public:
explicit Cic2Core(const unsigned div = 2) {
reset(div);
}
unsigned div() const { return div_; }
std::size_t filter(short *out, const short *in, std::size_t inlen);
void reset(unsigned div);
};
template<unsigned channels>
void Cic2Core<channels>::reset(const unsigned div) {
sum2 = sum1 = 0;
/*prev2 = */prev1 = 0;
this->div_ = div;
nextdivn = div;
// bufpos = div - 1;
}
template<unsigned channels>
std::size_t Cic2Core<channels>::filter(short *out, const short *const in, std::size_t inlen) {
// const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_;
const std::size_t produced = (inlen + div_ - nextdivn) / div_;
const long mul = 0x10000 / (div_ * div_); // trouble if div is too large, may be better to only support power of 2 div
const short *s = in;
/*unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
while (inlen >> 2) {
unsigned n = (inlen < BUFLEN ? inlen >> 2 : BUFLEN >> 2);
const unsigned end = n * 4;
unsigned i = 0;
do {
unsigned long s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
buf[i++] = sm2 += s1;
buf[i++] = sm2 += sm1;
s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
buf[i++] = sm2 += s1;
buf[i++] = sm2 += sm1;
} while (--n);
while (bufpos < end) {
const unsigned long out2 = buf[bufpos] - prev2;
prev2 = buf[bufpos];
bufpos += div_;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= end;
inlen -= end;
}
if (inlen) {
unsigned n = inlen;
unsigned i = 0;
do {
sm1 += static_cast<long>(*s);
s += channels;
buf[i++] = sm2 += sm1;
} while (--n);
while (bufpos < inlen) {
const unsigned long out2 = buf[bufpos] - prev2;
prev2 = buf[bufpos];
bufpos += div_;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= inlen;
}
sum1 = sm1;
sum2 = sm2;*/
unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
if (inlen >= nextdivn) {
{
unsigned divn = nextdivn;
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
} while (--divn);
const unsigned long out2 = sm2;
sm2 = 0;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
if (div_ & 1) {
std::size_t n = produced;
while (--n) {
unsigned divn = div_ >> 1;
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
} while (--divn);
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
*out = rshift16_round(static_cast<long>(sm2 - prev1) * mul);
out += channels;
prev1 = sm2;
sm2 = 0;
}
} else {
std::size_t n = produced;
while (--n) {
unsigned divn = div_ >> 1;
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
} while (--divn);
*out = rshift16_round(static_cast<long>(sm2 - prev1) * mul);
out += channels;
prev1 = sm2;
sm2 = 0;
}
}
nextdivn = div_;
}
{
unsigned divn = (in + inlen * channels - s) / channels;
nextdivn -= divn;
while (divn--) {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
}
}
sum1 = sm1;
sum2 = sm2;
return produced;
}
template<unsigned channels>
class Cic2 : public SubResampler {
Cic2Core<channels> cics[channels];
public:
enum { MAX_DIV = 64 };
explicit Cic2(unsigned div);
std::size_t resample(short *out, const short *in, std::size_t inlen);
unsigned mul() const { return 1; }
unsigned div() const { return cics[0].div(); }
};
template<unsigned channels>
Cic2<channels>::Cic2(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
cics[i].reset(div);
}
template<unsigned channels>
std::size_t Cic2<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i) {
samplesOut = cics[i].filter(out + i, in + i, inlen);
}
return samplesOut;
}
#endif

View File

@ -1,383 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CIC3_H
#define CIC3_H
#include "subresampler.h"
#include "rshift16_round.h"
template<unsigned channels>
class Cic3Core {
// enum { BUFLEN = 64 };
// unsigned long buf[BUFLEN];
unsigned long sum1;
unsigned long sum2;
unsigned long sum3;
unsigned long prev1;
unsigned long prev2;
unsigned long prev3;
unsigned div_;
unsigned nextdivn;
// unsigned bufpos;
public:
explicit Cic3Core(const unsigned div = 1) {
reset(div);
}
unsigned div() const { return div_; }
std::size_t filter(short *out, const short *in, std::size_t inlen);
void reset(unsigned div);
};
template<unsigned channels>
void Cic3Core<channels>::reset(const unsigned div) {
sum3 = sum2 = sum1 = 0;
prev3 = prev2 = prev1 = 0;
this->div_ = div;
nextdivn = div;
// bufpos = div - 1;
}
template<unsigned channels>
std::size_t Cic3Core<channels>::filter(short *out, const short *const in, std::size_t inlen) {
// const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_;
const std::size_t produced = (inlen + div_ - nextdivn) / div_;
const long mul = 0x10000 / (div_ * div_ * div_); // trouble if div is too large, may be better to only support power of 2 div
const short *s = in;
/*unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
while (inlen >> 1) {
unsigned n = (inlen < BUFLEN ? inlen >> 1 : BUFLEN >> 1);
const unsigned end = n * 2;
unsigned i = 0;
do {
unsigned long s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
unsigned long s2 = sm2 += s1;
sm2 += sm1;
buf[i++] = sm3 += s2;
buf[i++] = sm3 += sm2;
} while (--n);
while (bufpos < end) {
const unsigned long out3 = buf[bufpos] - prev3;
prev3 = buf[bufpos];
bufpos += div_;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= end;
inlen -= end;
}
if (inlen) {
unsigned n = inlen;
unsigned i = 0;
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
buf[i++] = sm3 += sm2;
} while (--n);
while (bufpos < inlen) {
const unsigned long out3 = buf[bufpos] - prev3;
prev3 = buf[bufpos];
bufpos += div_;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= inlen;
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;*/
unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
if (inlen >= nextdivn) {
unsigned divn = nextdivn;
std::size_t n = produced;
do {
do {
sm1 += static_cast<long>(*s);
sm2 += sm1;
sm3 += sm2;
s += channels;
} while (--divn);
const unsigned long out3 = sm3 - prev3;
prev3 = sm3;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
divn = div_;
} while (--n);
nextdivn = div_;
}
{
unsigned divn = (in + inlen * channels - s) / channels;
nextdivn -= divn;
while (divn--) {
sm1 += static_cast<long>(*s);
sm2 += sm1;
sm3 += sm2;
s += channels;
}
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;
return produced;
}
/*template<unsigned channels>
class Cic3EvenOddCore {
unsigned long sum1;
unsigned long sum2;
unsigned long sum3;
unsigned long prev1;
unsigned long prev2;
unsigned long prev3;
unsigned div_;
unsigned nextdivn;
static int getMul(unsigned div) {
return 0x10000 / (div * div * div); // trouble if div is too large, may be better to only support power of 2 div
}
void filterEven(short *out, const short *s, std::size_t n);
void filterOdd(short *out, const short *s, std::size_t n);
public:
Cic3EvenOddCore(const unsigned div = 2) {
reset(div);
}
unsigned div() const { return div_; }
std::size_t filter(short *out, const short *in, std::size_t inlen);
void reset(unsigned div);
};
template<unsigned channels>
void Cic3EvenOddCore<channels>::reset(const unsigned div) {
sum3 = sum2 = sum1 = 0;
prev3 = prev2 = prev1 = 0;
this->div_ = div;
nextdivn = div;
}
template<unsigned channels>
void Cic3EvenOddCore<channels>::filterEven(short *out, const short *s, std::size_t n) {
const int mul = getMul(div_);
unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
while (n--) {
{
unsigned sn = div_ >> 1;
do {
unsigned long s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
unsigned long s2 = sm2 += s1;
sm2 += sm1;
sm3 += s2;
sm3 += sm2;
} while (--sn);
}
const unsigned long out3 = sm3 - prev3;
prev3 = sm3;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;
}
template<unsigned channels>
void Cic3EvenOddCore<channels>::filterOdd(short *out, const short *s, std::size_t n) {
const int mul = getMul(div_);
unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
while (n--) {
{
unsigned sn = div_ >> 1;
do {
unsigned long s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
unsigned long s2 = sm2 += s1;
sm2 += sm1;
sm3 += s2;
sm3 += sm2;
} while (--sn);
}
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm3 += sm2;
const unsigned long out3 = sm3 - prev3;
prev3 = sm3;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;
}
template<unsigned channels>
std::size_t Cic3EvenOddCore<channels>::filter(short *out, const short *const in, std::size_t inlen) {
short *const outStart = out;
const short *s = in;
if (inlen >= nextdivn) {
{
{
unsigned divn = nextdivn;
do {
sum1 += static_cast<long>(*s);
s += channels;
sum2 += sum1;
sum3 += sum2;
} while (--divn);
}
const unsigned long out3 = sum3 - prev3;
prev3 = sum3;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * getMul(div_));
prev1 = out2;
out += channels;
}
std::size_t n = (inlen - nextdivn) / div_;
if (div_ & 1)
filterOdd(out, s, n);
else
filterEven(out, s, n);
s += n * div_ * channels;
out += n * channels;
nextdivn = div_;
}
{
unsigned divn = inlen - (s - in) / channels;
nextdivn -= divn;
while (divn--) {
sum1 += static_cast<long>(*s);
s += channels;
sum2 += sum1;
sum3 += sum2;
}
}
return (out - outStart) / channels;
}*/
template<unsigned channels>
class Cic3 : public SubResampler {
Cic3Core<channels> cics[channels];
public:
enum { MAX_DIV = 23 };
explicit Cic3(unsigned div);
std::size_t resample(short *out, const short *in, std::size_t inlen);
unsigned mul() const { return 1; }
unsigned div() const { return cics[0].div(); }
};
template<unsigned channels>
Cic3<channels>::Cic3(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
cics[i].reset(div);
}
template<unsigned channels>
std::size_t Cic3<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i) {
samplesOut = cics[i].filter(out + i, in + i, inlen);
}
return samplesOut;
}
#endif

View File

@ -1,238 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CIC4_H
#define CIC4_H
#include "subresampler.h"
#include "rshift16_round.h"
template<unsigned channels>
class Cic4Core {
enum { BUFLEN = 64 };
unsigned long buf[BUFLEN];
unsigned long sum1;
unsigned long sum2;
unsigned long sum3;
unsigned long sum4;
unsigned long prev1;
unsigned long prev2;
unsigned long prev3;
unsigned long prev4;
unsigned div_;
// unsigned nextdivn;
unsigned bufpos;
public:
explicit Cic4Core(const unsigned div = 1) {
reset(div);
}
unsigned div() const { return div_; }
std::size_t filter(short *out, const short *in, std::size_t inlen);
void reset(unsigned div);
};
template<unsigned channels>
void Cic4Core<channels>::reset(const unsigned div) {
sum4 = sum3 = sum2 = sum1 = 0;
prev4 = prev3 = prev2 = prev1 = 0;
this->div_ = div;
// nextdivn = div;
bufpos = div - 1;
}
template<unsigned channels>
std::size_t Cic4Core<channels>::filter(short *out, const short *const in, std::size_t inlen) {
const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_;
// const std::size_t produced = (inlen + div_ - nextdivn) / div_;
const long mul = 0x10000 / (div_ * div_ * div_ * div_); // trouble if div is too large, may be better to only support power of 2 div
const short *s = in;
unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
unsigned long sm4 = sum4;
while (inlen >> 2) {
unsigned n = (inlen < BUFLEN ? inlen >> 2 : BUFLEN >> 2);
const unsigned end = n * 4;
unsigned i = 0;
do {
unsigned long s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
unsigned long s2 = sm2 += s1;
sm2 += sm1;
unsigned long s3 = sm3 += s2;
sm3 += sm2;
buf[i++] = sm4 += s3;
buf[i++] = sm4 += sm3;
s1 = sm1 += static_cast<long>(*s);
s += channels;
sm1 += static_cast<long>(*s);
s += channels;
s2 = sm2 += s1;
sm2 += sm1;
s3 = sm3 += s2;
sm3 += sm2;
buf[i++] = sm4 += s3;
buf[i++] = sm4 += sm3;
} while (--n);
while (bufpos < end) {
const unsigned long out4 = buf[bufpos] - prev4;
prev4 = buf[bufpos];
bufpos += div_;
const unsigned long out3 = out4 - prev3;
prev3 = out4;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= end;
inlen -= end;
}
if (inlen) {
unsigned n = inlen;
unsigned i = 0;
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm3 += sm2;
buf[i++] = sm4 += sm3;
} while (--n);
while (bufpos < inlen) {
const unsigned long out4 = buf[bufpos] - prev4;
prev4 = buf[bufpos];
bufpos += div_;
const unsigned long out3 = out4 - prev3;
prev3 = out4;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
}
bufpos -= inlen;
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;
sum4 = sm4;
/*unsigned long sm1 = sum1;
unsigned long sm2 = sum2;
unsigned long sm3 = sum3;
unsigned long sm4 = sum4;
if (produced) {
unsigned divn = nextdivn;
std::size_t n = produced;
do {
do {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm3 += sm2;
sm4 += sm3;
} while (--divn);
const unsigned long out4 = sm4 - prev4;
prev4 = sm4;
const unsigned long out3 = out4 - prev3;
prev3 = out4;
const unsigned long out2 = out3 - prev2;
prev2 = out3;
*out = rshift16_round(static_cast<long>(out2 - prev1) * mul);
prev1 = out2;
out += channels;
divn = div_;
} while (--n);
nextdivn = div_;
}
{
unsigned divn = (in + inlen * channels - s) / channels;
nextdivn -= divn;
while (divn--) {
sm1 += static_cast<long>(*s);
s += channels;
sm2 += sm1;
sm3 += sm2;
sm4 += sm3;
}
}
sum1 = sm1;
sum2 = sm2;
sum3 = sm3;
sum4 = sm4;*/
return produced;
}
template<unsigned channels>
class Cic4 : public SubResampler {
Cic4Core<channels> cics[channels];
public:
enum { MAX_DIV = 13 };
explicit Cic4(unsigned div);
std::size_t resample(short *out, const short *in, std::size_t inlen);
unsigned mul() const { return 1; }
unsigned div() const { return cics[0].div(); }
};
template<unsigned channels>
Cic4<channels>::Cic4(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
cics[i].reset(div);
}
template<unsigned channels>
std::size_t Cic4<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i) {
samplesOut = cics[i].filter(out + i, in + i, inlen);
}
return samplesOut;
}
#endif

View File

@ -1,162 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CONVOLUTER_H
#define CONVOLUTER_H
#include <algorithm>
#include <cstring>
#include "gambatte-array.h"
#include "rshift16_round.h"
template<unsigned channels, unsigned phases>
class PolyPhaseConvoluter {
const short *kernel;
Array<short> prevbuf;
unsigned div_;
unsigned x_;
public:
PolyPhaseConvoluter() : kernel(0), div_(0), x_(0) {}
PolyPhaseConvoluter(const short *kernel, unsigned phaseLen, unsigned div) { reset(kernel, phaseLen, div); }
void reset(const short *kernel, unsigned phaseLen, unsigned div);
std::size_t filter(short *out, const short *in, std::size_t inlen);
void adjustDiv(const unsigned div) { this->div_ = div; }
unsigned div() const { return div_; }
};
template<unsigned channels, unsigned phases>
void PolyPhaseConvoluter<channels, phases>::reset(const short *const kernel, const unsigned phaseLen, const unsigned div) {
this->kernel = kernel;
this->div_ = div;
x_ = 0;
prevbuf.reset(phaseLen);
std::fill(prevbuf.get(), prevbuf.get() + phaseLen, 0);
}
template<unsigned channels, unsigned phases>
std::size_t PolyPhaseConvoluter<channels, phases>::filter(short *out, const short *const in, std::size_t inlen) {
if (!kernel || !inlen)
return 0;
// The gist of what happens here is given by the commented pseudo-code below.
// Note that the order of the kernel elements has been changed for efficiency in the real implementation.
/*for (std::size_t x = 0; x < inlen + M; ++x) {
const int end = x < inlen ? M + 1 : inlen + M - x;
int j = x < M ? M - x : 0;
j += (phases - (x - M + j) % phases) % phases; // adjust j so we don't start on a virtual 0 sample
for (; j < end; j += phases) {
buffer[x] += kernel[j] * start[(x - M + j) / phases];
}
}*/
// Slightly more optimized version.
/*for (std::size_t x = 0; x < inlen + M; ++x) {
const int end = x < inlen ? M + 1 : inlen + M - x;
int j = x < M ? M - x : 0;
j += (phases - (x - M + j) % phases) % phases; // adjust j so we don't start on a virtual 0 sample
const short *k = kernel + (j % phases) * phaseLen + j / phases;
const short *s = start + (x - M + j) / phases;
int n = ((end - j) + phases - 1) / phases;
do {
buffer[x] += *k++ * *s++;
} while (--n);
}*/
const std::size_t phaseLen = prevbuf.size();
const std::size_t M = phaseLen * phases - 1;
inlen *= phases;
std::size_t x = x_;
for (; x < (M < inlen ? M : inlen); x += div_) {
const short *k = kernel + ((x + 1) % phases) * phaseLen; // adjust phase so we don't start on a virtual 0 sample
const short *s = prevbuf + x / phases + 1;
long acc = 0;
unsigned n = prevbuf + phaseLen - s;
while (n--) {
acc += *k++ * *s++;
}
s = in;
n = x / phases + 1;
do {
acc += *k++ * *s;
s += channels;
} while (--n);
*out = rshift16_round(acc);
out += channels;
}
// We could easily get rid of the division and modulus here by updating the
// k and s pointers incrementally. However, we currently only use powers of 2
// and we would end up referencing more variables which often compiles to bad
// code on x86, which is why I'm also hesistant to get rid of the template arguments.
for (; x < inlen; x += div_) {
const short *k = kernel + ((x + 1) % phases) * phaseLen; // adjust phase so we don't start on a virtual 0 sample
const short *s = in + (x / phases + 1 - phaseLen) * channels;
long acc = 0;
// unsigned n = (M + 1/* - phase + phases - 1*/) / phases;
unsigned n = phaseLen;
do {
acc += *k++ * *s;
s += channels;
} while (--n);
*out = rshift16_round(acc);
out += channels;
}
const std::size_t produced = (x - x_) / div_;
x_ = x - inlen;
inlen /= phases;
{
short *p = prevbuf;
const short *s = in + (inlen - phaseLen) * channels;
unsigned n = phaseLen;
if (inlen < phaseLen) {
const unsigned i = phaseLen - inlen;
std::memmove(p, p + inlen, i * sizeof(short));
p += i;
n -= i;
s = in;
}
do {
*p++ = *s;
s += channels;
} while (--n);
}
return produced;
}
#endif

View File

@ -1,100 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef HAMMINGSINC_H
#define HAMMINGSINC_H
#include "convoluter.h"
#include "subresampler.h"
#include "makesinckernel.h"
#include "cic3.h"
#include "gambatte-array.h"
#include <cmath>
#include <cstdlib>
template<unsigned channels, unsigned phases>
class HammingSinc : public SubResampler {
PolyPhaseConvoluter<channels, phases> convoluters[channels];
Array<short> kernel;
static double hammingWin(const long i, const long M) {
static const double PI = 3.14159265358979323846;
return 0.53836 - 0.46164 * std::cos(2 * PI * i / M);
}
void init(unsigned div, unsigned phaseLen, double fc);
public:
enum { MUL = phases };
typedef Cic3<channels> Cic;
static float cicLimit() { return 4.2f; }
class RollOff {
static unsigned toTaps(const float rollOffWidth) {
static const float widthTimesTaps = 3.0f;
return static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth));
}
static float toFc(const float rollOffStart, const int taps) {
static const float startToFcDeltaTimesTaps = 1.27f;
return startToFcDeltaTimesTaps / taps + rollOffStart;
}
public:
const unsigned taps;
const float fc;
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
};
HammingSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); }
HammingSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void adjustDiv(unsigned div);
unsigned mul() const { return MUL; }
unsigned div() const { return convoluters[0].div(); }
};
template<unsigned channels, unsigned phases>
void HammingSinc<channels, phases>::init(const unsigned div, const unsigned phaseLen, const double fc) {
kernel.reset(phaseLen * phases);
makeSincKernel(kernel, phases, phaseLen, fc, hammingWin);
for (unsigned i = 0; i < channels; ++i)
convoluters[i].reset(kernel, phaseLen, div);
}
template<unsigned channels, unsigned phases>
std::size_t HammingSinc<channels, phases>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i)
samplesOut = convoluters[i].filter(out + i, in + i, inlen);
return samplesOut;
}
template<unsigned channels, unsigned phases>
void HammingSinc<channels, phases>::adjustDiv(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
convoluters[i].adjustDiv(div);
}
#endif

View File

@ -1,36 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "i0.h"
double i0(double x) {
double sum = 1.0;
double xpm_dmfac = 1.0;
double m = 1.0;
unsigned n = 16;
x = 0.25 * x * x;
do {
xpm_dmfac *= x / (m*m);
sum += xpm_dmfac;
m += 1.0;
} while (--n);
return sum;
}

View File

@ -1,24 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef I0_H
#define I0_H
double i0(double x);
#endif

View File

@ -1,107 +0,0 @@
/***************************************************************************
* Copyright (C) 2008-2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef KAISER50SINC_H
#define KAISER50SINC_H
#include "convoluter.h"
#include "subresampler.h"
#include "makesinckernel.h"
#include "i0.h"
#include "cic3.h"
#include "gambatte-array.h"
#include <cmath>
#include <cstdlib>
template<unsigned channels, unsigned phases>
class Kaiser50Sinc : public SubResampler {
PolyPhaseConvoluter<channels, phases> convoluters[channels];
Array<short> kernel;
static double kaiserWin(const long n, const long M) {
static const double beta = 4.62;
static const double i0beta_rec = 1.0 / i0(beta);
double x = static_cast<double>(n * 2) / M - 1.0;
x = x * x;
x = beta * std::sqrt(1.0 - x);
return i0(x) * i0beta_rec;
}
void init(unsigned div, unsigned phaseLen, double fc);
public:
enum { MUL = phases };
typedef Cic3<channels> Cic;
static float cicLimit() { return 4.2f; }
class RollOff {
static unsigned toTaps(const float rollOffWidth) {
static const float widthTimesTaps = 2.715f;
return static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth));
}
static float toFc(const float rollOffStart, const int taps) {
static const float startToFcDeltaTimesTaps = 1.2f;
return startToFcDeltaTimesTaps / taps + rollOffStart;
}
public:
const unsigned taps;
const float fc;
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
};
Kaiser50Sinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); }
Kaiser50Sinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void adjustDiv(unsigned div);
unsigned mul() const { return MUL; }
unsigned div() const { return convoluters[0].div(); }
};
template<unsigned channels, unsigned phases>
void Kaiser50Sinc<channels, phases>::init(const unsigned div, const unsigned phaseLen, const double fc) {
kernel.reset(phaseLen * phases);
makeSincKernel(kernel, phases, phaseLen, fc, kaiserWin);
for (unsigned i = 0; i < channels; ++i)
convoluters[i].reset(kernel, phaseLen, div);
}
template<unsigned channels, unsigned phases>
std::size_t Kaiser50Sinc<channels, phases>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i)
samplesOut = convoluters[i].filter(out + i, in + i, inlen);
return samplesOut;
}
template<unsigned channels, unsigned phases>
void Kaiser50Sinc<channels, phases>::adjustDiv(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
convoluters[i].adjustDiv(div);
}
#endif

View File

@ -1,107 +0,0 @@
/***************************************************************************
* Copyright (C) 2008-2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef KAISER70SINC_H
#define KAISER70SINC_H
#include "convoluter.h"
#include "subresampler.h"
#include "makesinckernel.h"
#include "i0.h"
#include "cic4.h"
#include "gambatte-array.h"
#include <cmath>
#include <cstdlib>
template<unsigned channels, unsigned phases>
class Kaiser70Sinc : public SubResampler {
PolyPhaseConvoluter<channels, phases> convoluters[channels];
Array<short> kernel;
static double kaiserWin(const long n, const long M) {
static const double beta = 6.9;
static const double i0beta_rec = 1.0 / i0(beta);
double x = static_cast<double>(n * 2) / M - 1.0;
x = x * x;
x = beta * std::sqrt(1.0 - x);
return i0(x) * i0beta_rec;
}
void init(unsigned div, unsigned phaseLen, double fc);
public:
enum { MUL = phases };
typedef Cic4<channels> Cic;
static float cicLimit() { return 4.7f; }
class RollOff {
static unsigned toTaps(const float rollOffWidth) {
static const float widthTimesTaps = 3.75f;
return static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth));
}
static float toFc(const float rollOffStart, const int taps) {
static const float startToFcDeltaTimesTaps = 1.5f;
return startToFcDeltaTimesTaps / taps + rollOffStart;
}
public:
const unsigned taps;
const float fc;
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
};
Kaiser70Sinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); }
Kaiser70Sinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void adjustDiv(unsigned div);
unsigned mul() const { return MUL; }
unsigned div() const { return convoluters[0].div(); }
};
template<unsigned channels, unsigned phases>
void Kaiser70Sinc<channels, phases>::init(const unsigned div, const unsigned phaseLen, const double fc) {
kernel.reset(phaseLen * phases);
makeSincKernel(kernel, phases, phaseLen, fc, kaiserWin);
for (unsigned i = 0; i < channels; ++i)
convoluters[i].reset(kernel, phaseLen, div);
}
template<unsigned channels, unsigned phases>
std::size_t Kaiser70Sinc<channels, phases>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i)
samplesOut = convoluters[i].filter(out + i, in + i, inlen);
return samplesOut;
}
template<unsigned channels, unsigned phases>
void Kaiser70Sinc<channels, phases>::adjustDiv(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
convoluters[i].adjustDiv(div);
}
#endif

View File

@ -1,134 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef LININT_H
#define LININT_H
#include <cstddef>
#include "../resampler.h"
#include "u48div.h"
#include "rshift16_round.h"
template<unsigned channels>
class LinintCore {
unsigned long ratio;
std::size_t pos_;
unsigned fracPos_;
int prevSample_;
public:
LinintCore(long inRate = 1, long outRate = 1) { init(inRate, outRate); }
void adjustRate(long inRate, long outRate) {
ratio = static_cast<unsigned long>((static_cast<double>(inRate) / outRate) * 0x10000 + 0.5);
}
void exactRatio(unsigned long &mul, unsigned long &div) const { mul = 0x10000; div = ratio; }
void init(long inRate, long outRate);
std::size_t maxOut(std::size_t inlen) const { return inlen ? u48div(inlen - 1, 0xFFFF, ratio) + 1 : 0; }
std::size_t resample(short *out, const short *in, std::size_t inlen);
};
template<unsigned channels>
void LinintCore<channels>::init(const long inRate, const long outRate) {
adjustRate(inRate, outRate);
pos_ = (ratio >> 16) + 1;
fracPos_ = ratio & 0xFFFF;
prevSample_ = 0;
}
template<unsigned channels>
std::size_t LinintCore<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t opos = 0;
std::size_t pos = pos_;
unsigned fracPos = fracPos_;
int prevSample = prevSample_;
if (pos < inlen) {
if (pos != 0)
prevSample = in[(pos-1) * channels];
for (;;) {
out[opos] = prevSample + rshift16_round((in[pos * channels] - prevSample) * static_cast<long>(fracPos));
opos += channels;
{
const unsigned long next = ratio + fracPos;
pos += next >> 16;
fracPos = next & 0xFFFF;
}
if (pos < inlen) {
prevSample = in[(pos-1) * channels];
} else
break;
}
if (pos == inlen)
prevSample = in[(pos-1) * channels];
}
// const std::size_t produced = ((pos - pos_) * 0x10000 + fracPos - fracPos_) / ratio;
pos_ = pos - inlen;
fracPos_ = fracPos;
prevSample_ = prevSample;
return opos / channels;
}
template<unsigned channels>
class Linint : public Resampler {
LinintCore<channels> cores[channels];
public:
Linint(long inRate, long outRate);
void adjustRate(long inRate, long outRate);
void exactRatio(unsigned long &mul, unsigned long &div) const { cores[0].exactRatio(mul, div); }
std::size_t maxOut(std::size_t inlen) const { return cores[0].maxOut(inlen); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
};
template<unsigned channels>
Linint<channels>::Linint(const long inRate, const long outRate) {
setRate(inRate, outRate);
for (unsigned i = 0; i < channels; ++i)
cores[i].init(inRate, outRate);
}
template<unsigned channels>
void Linint<channels>::adjustRate(const long inRate, const long outRate) {
setRate(inRate, outRate);
for (unsigned i = 0; i < channels; ++i)
cores[i].adjustRate(inRate, outRate);
}
template<unsigned channels>
std::size_t Linint<channels>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t outlen = 0;
for (unsigned i = 0; i < channels; ++i)
outlen = cores[i].resample(out + i, in + i, inlen);
return outlen;
}
#endif

View File

@ -1,142 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "makesinckernel.h"
#include "gambatte-array.h"
void makeSincKernel(short *const kernel, const unsigned phases, const unsigned phaseLen, double fc, double (*win)(const long m, const long M)) {
static const double PI = 3.14159265358979323846;
fc /= phases;
/*{
const Array<double> dkernel(phaseLen * phases);
const long M = static_cast<long>(phaseLen) * phases - 1;
for (long i = 0; i < M + 1; ++i) {
const double sinc = i * 2 == M ?
PI * fc :
std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M);
dkernel[((phases - (i % phases)) % phases) * phaseLen + i / phases] = win(i, M) * sinc;
}
double maxabsgain = 0;
for (unsigned ph = 0; ph < phases; ++ph) {
double gain = 0;
double absgain = 0;
for (unsigned i = 0; i < phaseLen; ++i) {
gain += dkernel[ph * phaseLen + i];
absgain += std::abs(dkernel[ph * phaseLen + i]);
}
gain = 1.0 / gain;
// Per phase normalization to avoid DC fluctuations.
for (unsigned i = 0; i < phaseLen; ++i)
dkernel[ph * phaseLen + i] *= gain;
absgain *= gain;
if (absgain > maxabsgain)
maxabsgain = absgain;
}
const double gain = (0x10000 - 0.5 * phaseLen) / maxabsgain;
for (long i = 0; i < M + 1; ++i)
kernel[i] = std::floor(dkernel[i] * gain + 0.5);
}*/
// The following is equivalent to the more readable version above
const long M = static_cast<long>(phaseLen) * phases - 1;
const Array<double> dkernel(M / 2 + 1);
{
double *dk = dkernel;
for (unsigned ph = 0; ph < phases; ++ph) {
for (long i = ph; i < M / 2 + 1; i += phases) {
const double sinc = i * 2 == M ?
PI * fc :
std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M);
*dk++ = win(i, M) * sinc;
}
}
}
double maxabsgain = 0.0;
{
double *dkp1 = dkernel;
double *dkp2 = dkernel + M / 2;
for (unsigned ph = 0; ph < (phases + 1) / 2; ++ph) {
double gain = 0.0;
double absgain = 0.0;
{
const double *kp1 = dkp1;
const double *kp2 = dkp2;
long i = ph;
for (; i < M / 2 + 1; i += phases) {
gain += *kp1;
absgain += std::abs(*kp1++);
}
for (; i < M + 1; i += phases) {
gain += *kp2;
absgain += std::abs(*kp2--);
}
}
gain = 1.0 / gain;
long i = ph;
for (; i < M / 2 + 1; i += phases)
*dkp1++ *= gain;
if (dkp1 < dkp2) {
for (; i < M + 1; i += phases)
*dkp2-- *= gain;
}
absgain *= gain;
if (absgain > maxabsgain)
maxabsgain = absgain;
}
}
const double gain = (0x10000 - 0.5 * phaseLen) / maxabsgain;
const double *dk = dkernel;
for (unsigned ph = 0; ph < phases; ++ph) {
short *k = kernel + ((phases - ph) % phases) * phaseLen;
short *km = kernel + phaseLen - 1 + ((ph + 1) % phases) * phaseLen;
for (long i = ph; i < M / 2 + 1; i += phases)
*km-- = *k++ = static_cast<short>(std::floor(*dk++ * gain + 0.5));
}
}

View File

@ -1,28 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef MAKE_SINC_KERNEL_H
#define MAKE_SINC_KERNEL_H
#include <cmath>
#include <cstdlib>
void makeSincKernel(short *kernel, unsigned phases,
unsigned phaseLen, double fc, double (*win)(const long m, const long M));
#endif

View File

@ -1,99 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RECTSINC_H
#define RECTSINC_H
#include "convoluter.h"
#include "subresampler.h"
#include "makesinckernel.h"
#include "cic2.h"
#include "gambatte-array.h"
#include <cmath>
#include <cstdlib>
template<unsigned channels, unsigned phases>
class RectSinc : public SubResampler {
PolyPhaseConvoluter<channels, phases> convoluters[channels];
Array<short> kernel;
static double rectWin(const long /*i*/, const long /*M*/) {
return 1;
}
void init(unsigned div, unsigned phaseLen, double fc);
public:
enum { MUL = phases };
typedef Cic2<channels> Cic;
static float cicLimit() { return 2.0f; }
class RollOff {
static unsigned toTaps(const float rollOffWidth) {
static const float widthTimesTaps = 0.9f;
return static_cast<unsigned>(std::ceil(widthTimesTaps / rollOffWidth));
}
static float toFc(const float rollOffStart, const int taps) {
static const float startToFcDeltaTimesTaps = 0.43f;
return startToFcDeltaTimesTaps / taps + rollOffStart;
}
public:
const unsigned taps;
const float fc;
RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {}
};
RectSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); }
RectSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); }
std::size_t resample(short *out, const short *in, std::size_t inlen);
void adjustDiv(unsigned div);
unsigned mul() const { return MUL; }
unsigned div() const { return convoluters[0].div(); }
};
template<unsigned channels, unsigned phases>
void RectSinc<channels, phases>::init(const unsigned div, const unsigned phaseLen, const double fc) {
kernel.reset(phaseLen * phases);
makeSincKernel(kernel, phases, phaseLen, fc, rectWin);
for (unsigned i = 0; i < channels; ++i)
convoluters[i].reset(kernel, phaseLen, div);
}
template<unsigned channels, unsigned phases>
std::size_t RectSinc<channels, phases>::resample(short *const out, const short *const in, const std::size_t inlen) {
std::size_t samplesOut;
for (unsigned i = 0; i < channels; ++i)
samplesOut = convoluters[i].filter(out + i, in + i, inlen);
return samplesOut;
}
template<unsigned channels, unsigned phases>
void RectSinc<channels, phases>::adjustDiv(const unsigned div) {
for (unsigned i = 0; i < channels; ++i)
convoluters[i].adjustDiv(div);
}
#endif

View File

@ -1,50 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "../resamplerinfo.h"
#include "chainresampler.h"
#include "kaiser50sinc.h"
#include "kaiser70sinc.h"
// #include "hammingsinc.h"
// #include "blackmansinc.h"
#include "rectsinc.h"
#include "linint.h"
struct LinintInfo {
static Resampler* create(long inRate, long outRate, std::size_t) { return new Linint<ChainResampler::channels>(inRate, outRate); }
};
template<template<unsigned,unsigned> class T>
struct ChainSincInfo {
static Resampler* create(long inRate, long outRate, std::size_t periodSz) {
ChainResampler *r = new ChainResampler;
r->init<T>(inRate, outRate, periodSz);
return r;
}
};
const ResamplerInfo ResamplerInfo::resamplers[] = {
{ "Fast", LinintInfo::create },
{ "High quality (CIC + sinc chain)", ChainSincInfo<RectSinc>::create },
// { "Hamming windowed sinc (~50 dB SNR)", ChainSincInfo<HammingSinc>::create },
// { "Blackman windowed sinc (~70 dB SNR)", ChainSincInfo<BlackmanSinc>::create },
{ "Very high quality (CIC + sinc chain)", ChainSincInfo<Kaiser50Sinc>::create },
{ "Highest quality (CIC + sinc chain)", ChainSincInfo<Kaiser70Sinc>::create }
};
const unsigned ResamplerInfo::num_ = sizeof(ResamplerInfo::resamplers) / sizeof(ResamplerInfo);

View File

@ -1,32 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RSHIFT16_ROUND_H
#define RSHIFT16_ROUND_H
#ifdef NO_NEGATIVE_SHIFT
static inline long rshift16_round(const long l) {
return l < 0 ? -((-l + 0x8000) >> 16) : (l + 0x8000) >> 16;
}
#else
static inline long rshift16_round(const long l) {
return (l + 0x8000) >> 16;
}
#endif
#endif

View File

@ -1,33 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef SUBRESAMPLER_H
#define SUBRESAMPLER_H
#include <cstddef>
class SubResampler {
public:
virtual std::size_t resample(short *out, const short *in, std::size_t inlen) = 0;
virtual unsigned mul() const = 0;
virtual unsigned div() const = 0;
virtual void adjustDiv(unsigned /*div*/) {}
virtual ~SubResampler() {}
};
#endif

View File

@ -1,54 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "u48div.h"
unsigned long u48div(unsigned long num1, unsigned num2, const unsigned long den) {
unsigned long res = 0;
unsigned s = 16;
do {
if (num1 < 0x10000) {
num1 <<= s;
num1 |= num2 & ((1 << s) - 1);
s = 0;
} else {
if (num1 < 0x1000000) {
const unsigned maxs = s < 8 ? s : 8;
num1 <<= maxs;
num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1);
}
if (num1 < 0x10000000) {
const unsigned maxs = s < 4 ? s : 4;
num1 <<= maxs;
num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1);
}
while (num1 < den && s) {
num1 <<= 1; // if this overflows we're screwed
num1 |= num2 >> --s & 1;
}
}
res += (num1 / den) << s;
num1 = (num1 % den);
} while (s);
return res;
}

View File

@ -1,24 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef U48DIV_H
#define U48DIV_H
unsigned long u48div(unsigned long num1, unsigned num2, unsigned long den);
#endif

View File

@ -1,51 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef UPSAMPLER_H
#define UPSAMPLER_H
#include "subresampler.h"
#include <cstring>
template<unsigned channels>
class Upsampler : public SubResampler {
unsigned mul_;
public:
Upsampler(const unsigned mul) : mul_(mul) {}
std::size_t resample(short *out, const short *in, std::size_t inlen);
unsigned mul() const { return mul_; }
unsigned div() const { return 1; }
};
template<unsigned channels>
std::size_t Upsampler<channels>::resample(short *out, const short *in, std::size_t inlen) {
if (inlen) {
std::memset(out, 0, inlen * mul_ * sizeof(short) * channels);
do {
std::memcpy(out, in, sizeof(short) * channels);
in += channels;
out += mul_ * channels;
} while (--inlen);
}
return inlen * mul_;
}
#endif

View File

@ -1,112 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#include "gambatte-array.h"
#include <cstddef>
#include <algorithm>
#include <cstring>
template<typename T>
class RingBuffer {
Array<T> buf;
std::size_t sz;
std::size_t rpos;
std::size_t wpos;
public:
RingBuffer(const std::size_t sz_in = 0) : sz(0), rpos(0), wpos(0) { reset(sz_in); }
std::size_t avail() const {
return (wpos < rpos ? 0 : sz) + rpos - wpos - 1;
}
void clear() {
wpos = rpos = 0;
}
void fill(T value);
void read(T *out, std::size_t num);
void reset(std::size_t sz_in);
std::size_t size() const {
return sz - 1;
}
std::size_t used() const {
return (wpos < rpos ? sz : 0) + wpos - rpos;
}
void write(const T *in, std::size_t num);
};
template<typename T>
void RingBuffer<T>::fill(const T value) {
std::fill(buf + 0, buf + sz, value);
rpos = 0;
wpos = sz - 1;
}
template<typename T>
void RingBuffer<T>::read(T *out, std::size_t num) {
if (rpos + num > sz) {
const std::size_t n = sz - rpos;
std::memcpy(out, buf + rpos, n * sizeof(T));
rpos = 0;
num -= n;
out += n;
}
std::memcpy(out, buf + rpos, num * sizeof(T));
if ((rpos += num) == sz)
rpos = 0;
}
template<typename T>
void RingBuffer<T>::reset(const std::size_t sz_in) {
sz = sz_in + 1;
rpos = wpos = 0;
buf.reset(sz_in ? sz : 0);
}
template<typename T>
void RingBuffer<T>::write(const T *in, std::size_t num) {
if (wpos + num > sz) {
const std::size_t n = sz - wpos;
std::memcpy(buf + wpos, in, n * sizeof(T));
wpos = 0;
num -= n;
in += n;
}
std::memcpy(buf + wpos, in, num * sizeof(T));
if ((wpos += num) == sz)
wpos = 0;
}
#endif

View File

@ -1,35 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "skipsched.h"
bool SkipSched::skipNext(bool skip) {
if (skipped) {
if (skipped < skippedmax / 2)
skip = true;
else
skipped = skip = 0;
} else if (skip) {
skippedmax += skippedmax / 2 < 8;
} else if (skippedmax / 2)
--skippedmax;
skipped += skip;
return skip;
}

View File

@ -1,37 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef SKIPSCHED_H
#define SKIPSCHED_H
class SkipSched {
unsigned skipped;
unsigned skippedmax;
public:
SkipSched() { reset(); }
void reset() {
skipped = 0;
skippedmax = 2 - 1;
}
bool skipNext(bool wantskip);
};
#endif

View File

@ -1,31 +0,0 @@
/***************************************************************************
* Copyright (C) 2008 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef USEC_H
#define USEC_H
typedef unsigned long usec_t;
static inline usec_t negate(usec_t t) {
return usec_t(0) - t;
}
usec_t getusecs();
void usecsleep(usec_t usecs);
#endif

View File

@ -1,157 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "rgb32conv.h"
#include "videolink.h"
#include "gambatte-array.h"
#include "gbint.h"
#include <algorithm>
namespace {
class Rgb32ToUyvy {
struct CacheUnit {
gambatte::uint_least32_t rgb32;
gambatte::uint_least32_t uyvy;
};
enum { cache_size = 0x100 };
enum { cache_mask = cache_size - 1 };
CacheUnit cache[cache_size];
public:
Rgb32ToUyvy();
void operator()(const gambatte::uint_least32_t *s, gambatte::uint_least32_t *d,
unsigned w, unsigned h, int srcPitch, int dstPitch);
};
Rgb32ToUyvy::Rgb32ToUyvy() {
#ifdef WORDS_BIGENDIAN
const CacheUnit c = { 0, 128ul << 24 | 16ul << 16 | 128 << 8 | 16 };
#else
const CacheUnit c = { 0, 16ul << 24 | 128ul << 16 | 16 << 8 | 128 };
#endif
std::fill(cache, cache + cache_size, c);
}
void Rgb32ToUyvy::operator()(const gambatte::uint_least32_t *s,
gambatte::uint_least32_t *d, const unsigned w, unsigned h, const int s_pitch, const int d_pitch)
{
while (h--) {
unsigned n = w >> 1;
do {
if ((cache[*s & cache_mask].rgb32 - *s) | (cache[*(s+1) & cache_mask].rgb32 - *(s+1))) {
cache[*s & cache_mask].rgb32 = *s;
cache[*(s+1) & cache_mask].rgb32 = *(s+1);
const unsigned long r = (*s >> 16 & 0x000000FF) | (*(s+1) & 0x00FF0000);
const unsigned long g = (*s >> 8 & 0x000000FF) | (*(s+1) << 8 & 0x00FF0000);
const unsigned long b = (*s & 0x000000FF) | (*(s+1) << 16 & 0x00FF0000);
const unsigned long y = r * 66 + g * 129 + b * 25 + ( 16 * 256 + 128) * 0x00010001ul;
const unsigned long u = b * 112 - r * 38 - g * 74 + (128 * 256 + 128) * 0x00010001ul;
const unsigned long v = r * 112 - g * 94 - b * 18 + (128 * 256 + 128) * 0x00010001ul;
#ifdef WORDS_BIGENDIAN
cache[*s & cache_mask].uyvy = (u << 16 & 0xFF000000) | (y << 8 & 0x00FF0000) | (v & 0x0000FF00) | (y >> 8 & 0x000000FF);
cache[*(s+1) & cache_mask].uyvy = (u & 0xFF000000) | (y >> 8 & 0x00FF0000) | (v >> 16 & 0x0000FF00) | y >> 24;
#else
cache[*s & cache_mask].uyvy = (y << 16 & 0xFF000000) | (v << 8 & 0x00FF0000) | (y & 0x0000FF00) | (u >> 8 & 0x000000FF);
cache[*(s+1) & cache_mask].uyvy = (y & 0xFF000000) | (v >> 8 & 0x00FF0000) | (y >> 16 & 0x0000FF00) | u >> 24;
#endif
}
*d = cache[*s & cache_mask].uyvy;
*(d+1) = cache[*(s+1) & cache_mask].uyvy;
s += 2;
d += 2;
} while (--n);
s += s_pitch - static_cast<int>(w);
d += d_pitch - static_cast<int>(w);
}
}
static void rgb32ToRgb16(const gambatte::uint_least32_t *s, gambatte::uint_least16_t *d,
const unsigned w, unsigned h, const int srcPitch, const int dstPitch)
{
do {
unsigned n = w;
do {
*d++ = (*s >> 8 & 0xF800) | (*s >> 5 & 0x07E0) | (*s >> 3 & 0x001F);
++s;
} while (--n);
s += srcPitch - static_cast<int>(w);
d += dstPitch - static_cast<int>(w);
} while (--h);
}
class Rgb32ToUyvyLink : public VideoLink {
const Array<gambatte::uint_least32_t> inbuf_;
Rgb32ToUyvy rgb32ToUyvy;
const unsigned width_;
const unsigned height_;
public:
Rgb32ToUyvyLink(unsigned width, unsigned height)
: inbuf_(static_cast<std::size_t>(width) * height),
width_(width),
height_(height)
{
}
virtual void* inBuf() const { return inbuf_; }
virtual int inPitch() const { return width_; }
virtual void draw(void *dst, int dstpitch) {
rgb32ToUyvy(inbuf_, static_cast<gambatte::uint_least32_t*>(dst), width_, height_, inPitch(), dstpitch);
}
};
class Rgb32ToRgb16Link : public VideoLink {
const Array<gambatte::uint_least32_t> inbuf_;
const unsigned width_;
const unsigned height_;
public:
Rgb32ToRgb16Link(unsigned width, unsigned height)
: inbuf_(static_cast<std::size_t>(width) * height),
width_(width),
height_(height)
{
}
virtual void* inBuf() const { return inbuf_; }
virtual int inPitch() const { return width_; }
virtual void draw(void *dst, int dstpitch) {
rgb32ToRgb16(inbuf_, static_cast<gambatte::uint_least16_t*>(dst), width_, height_, inPitch(), dstpitch);
}
};
}
VideoLink* Rgb32Conv::create(PixelFormat pf, unsigned width, unsigned height) {
switch (pf) {
case RGB16: return new Rgb32ToRgb16Link(width, height);
case UYVY: return new Rgb32ToUyvyLink(width, height);
default: return 0;
}
}

View File

@ -1,30 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef RGB32CONV_H
#define RGB32CONV_H
class VideoLink;
class Rgb32Conv {
public:
enum PixelFormat { RGB32, RGB16, UYVY };
static VideoLink* create(PixelFormat pf, unsigned width, unsigned height);
};
#endif

View File

@ -1,48 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "vfilterinfo.h"
#include "vfilters/catrom2x.h"
#include "vfilters/catrom3x.h"
#include "vfilters/kreed2xsai.h"
#include "vfilters/maxsthq2x.h"
#include "vfilters/maxsthq3x.h"
static VideoLink* createNone() { return 0; }
template<class T>
static VideoLink* createT() { return new T; }
#define VFINFO(handle, Type) { handle, Type::OUT_WIDTH, Type::OUT_HEIGHT, createT<Type> }
static const VfilterInfo vfinfos[] = {
{ "None", VfilterInfo::IN_WIDTH, VfilterInfo::IN_HEIGHT, createNone },
VFINFO("Bicubic Catmull-Rom spline 2x", Catrom2x),
VFINFO("Bicubic Catmull-Rom spline 3x", Catrom3x),
VFINFO("Kreed's 2xSaI", Kreed2xSaI),
VFINFO("MaxSt's hq2x", MaxStHq2x),
VFINFO("MaxSt's hq3x", MaxStHq3x)
};
std::size_t VfilterInfo::numVfilters() {
return sizeof(vfinfos) / sizeof(vfinfos[0]);
}
const VfilterInfo& VfilterInfo::get(std::size_t n) {
return vfinfos[n];
}

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef VFILTERINFO_H
#define VFILTERINFO_H
#include <cstddef>
class VideoLink;
struct VfilterInfo {
enum { IN_WIDTH = 160 };
enum { IN_HEIGHT = 144 };
const char *handle;
unsigned outWidth;
unsigned outHeight;
VideoLink* (*create)();
static const VfilterInfo& get(std::size_t n);
static std::size_t numVfilters();
};
#endif

View File

@ -1,179 +0,0 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "catrom2x.h"
#include <algorithm>
namespace {
enum { WIDTH = VfilterInfo::IN_WIDTH };
enum { HEIGHT = VfilterInfo::IN_HEIGHT };
enum { PITCH = WIDTH + 3 };
struct Colorsum {
gambatte::uint_least32_t r, g, b;
};
static void merge_columns(gambatte::uint_least32_t *dest, const Colorsum *sums) {
unsigned w = WIDTH;
while (w--) {
{
gambatte::uint_least32_t rsum = sums[1].r;
gambatte::uint_least32_t gsum = sums[1].g;
gambatte::uint_least32_t bsum = sums[1].b;
if (rsum & 0x80000000) rsum = 0;
if (gsum & 0x80000000) gsum = 0;
if (bsum & 0x80000000) bsum = 0;
rsum <<= 12;
rsum += 0x008000;
gsum >>= 4;
gsum += 0x0080;
bsum += 0x0008;
bsum >>= 4;
if (rsum > 0xFF0000) rsum = 0xFF0000;
if (gsum > 0x00FF00) gsum = 0x00FF00;
if (bsum > 0x0000FF) bsum = 0x0000FF;
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
}
{
gambatte::uint_least32_t rsum = sums[1].r * 9;
gambatte::uint_least32_t gsum = sums[1].g * 9;
gambatte::uint_least32_t bsum = sums[1].b * 9;
rsum -= sums[0].r;
gsum -= sums[0].g;
bsum -= sums[0].b;
rsum += sums[2].r * 9;
gsum += sums[2].g * 9;
bsum += sums[2].b * 9;
rsum -= sums[3].r;
gsum -= sums[3].g;
bsum -= sums[3].b;
if (rsum & 0x80000000) rsum = 0;
if (gsum & 0x80000000) gsum = 0;
if (bsum & 0x80000000) bsum = 0;
rsum <<= 8;
rsum += 0x008000;
gsum >>= 8;
gsum += 0x000080;
bsum += 0x000080;
bsum >>= 8;
if (rsum > 0xFF0000) rsum = 0xFF0000;
if (gsum > 0x00FF00) gsum = 0x00FF00;
if (bsum > 0x0000FF) bsum = 0x0000FF;
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
}
++sums;
}
}
static void filter(gambatte::uint_least32_t *dline, const int pitch, const gambatte::uint_least32_t *sline) {
Colorsum sums[PITCH];
for (unsigned h = HEIGHT; h--;) {
{
const gambatte::uint_least32_t *s = sline;
Colorsum *sum = sums;
unsigned n = PITCH;
while (n--) {
unsigned long pixel = *s;
sum->r = pixel >> 12 & 0x000FF0 ;
pixel <<= 4;
sum->g = pixel & 0x0FF000;
sum->b = pixel & 0x000FF0;
++s;
++sum;
}
}
merge_columns(dline, sums);
dline += pitch;
{
const gambatte::uint_least32_t *s = sline;
Colorsum *sum = sums;
unsigned n = PITCH;
while (n--) {
unsigned long pixel = *s;
unsigned long rsum = (pixel >> 16) * 9;
unsigned long gsum = (pixel & 0x00FF00) * 9;
unsigned long bsum = (pixel & 0x0000FF) * 9;
pixel = s[-1*PITCH];
rsum -= pixel >> 16;
gsum -= pixel & 0x00FF00;
bsum -= pixel & 0x0000FF;
pixel = s[1*PITCH];
rsum += (pixel >> 16) * 9;
gsum += (pixel & 0x00FF00) * 9;
bsum += (pixel & 0x0000FF) * 9;
pixel = s[2*PITCH];
rsum -= pixel >> 16;
gsum -= pixel & 0x00FF00;
bsum -= pixel & 0x0000FF;
sum->r = rsum;
sum->g = gsum;
sum->b = bsum;
++s;
++sum;
}
}
merge_columns(dline, sums);
dline += pitch;
sline += PITCH;
}
}
}
Catrom2x::Catrom2x()
: buffer_((HEIGHT + 3UL) * PITCH)
{
std::fill_n(buffer_.get(), buffer_.size(), 0);
}
void* Catrom2x::inBuf() const {
return buffer_ + PITCH + 1;
}
int Catrom2x::inPitch() const {
return PITCH;
}
void Catrom2x::draw(void *const dbuffer, const int pitch) {
::filter(static_cast<gambatte::uint_least32_t*>(dbuffer), pitch, buffer_ + PITCH);
}

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CATROM2X_H
#define CATROM2X_H
#include "../videolink.h"
#include "../vfilterinfo.h"
#include "gambatte-array.h"
#include "gbint.h"
class Catrom2x : public VideoLink {
const Array<gambatte::uint_least32_t> buffer_;
public:
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
Catrom2x();
virtual void* inBuf() const;
virtual int inPitch() const;
virtual void draw(void *dst, int dstpitch);
};
#endif

View File

@ -1,345 +0,0 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "catrom3x.h"
#include <algorithm>
namespace {
enum { WIDTH = VfilterInfo::IN_WIDTH };
enum { HEIGHT = VfilterInfo::IN_HEIGHT };
enum { PITCH = WIDTH + 3 };
struct Colorsum {
gambatte::uint_least32_t r, g, b;
};
static void merge_columns(gambatte::uint_least32_t *dest, const Colorsum *sums) {
unsigned w = WIDTH;
while (w--) {
{
gambatte::uint_least32_t rsum = sums[1].r;
gambatte::uint_least32_t gsum = sums[1].g;
gambatte::uint_least32_t bsum = sums[1].b;
if (rsum & 0x80000000)
rsum = 0;
else if (rsum > 6869)
rsum = 0xFF0000;
else {
rsum *= 607;
rsum <<= 2;
rsum += 0x008000;
rsum &= 0xFF0000;
}
if (gsum & 0x80000000)
gsum = 0;
else if (gsum > 1758567)
gsum = 0xFF00;
else {
gsum *= 607;
gsum >>= 14;
gsum += 0x000080;
gsum &= 0x00FF00;
}
if (bsum & 0x80000000)
bsum = 0;
else if (bsum > 6869)
bsum = 0xFF;
else {
bsum *= 607;
bsum += 8192;
bsum >>= 14;
}
/*rsum/=27;
rsum<<=8;
gsum/=27;
gsum<<=5;
bsum<<=4;
bsum+=27;
bsum/=54;
rsum+=0x008000;
gsum+=0x000080;
if(rsum>0xFF0000) rsum=0xFF0000;
if(gsum>0x00FF00) gsum=0x00FF00;
if(bsum>0x0000FF) bsum=0x0000FF;*/
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
}
{
gambatte::uint_least32_t rsum = sums[1].r * 21;
gambatte::uint_least32_t gsum = sums[1].g * 21;
gambatte::uint_least32_t bsum = sums[1].b * 21;
rsum -= sums[0].r << 1;
gsum -= sums[0].g << 1;
bsum -= sums[0].b << 1;
rsum += sums[2].r * 9;
gsum += sums[2].g * 9;
bsum += sums[2].b * 9;
rsum -= sums[3].r;
gsum -= sums[3].g;
bsum -= sums[3].b;
if (rsum & 0x80000000)
rsum = 0;
else if (rsum > 185578)
rsum = 0xFF0000;
else {
rsum *= 719;
rsum >>= 3;
rsum += 0x008000;
rsum &= 0xFF0000;
}
if (gsum & 0x80000000)
gsum = 0;
else if (gsum > 47508223)
gsum = 0x00FF00;
else {
gsum >>= 8;
gsum *= 719;
gsum >>= 11;
gsum += 0x000080;
gsum &= 0x00FF00;
}
if (bsum & 0x80000000)
bsum = 0;
else if (bsum > 185578)
bsum = 0x0000FF;
else {
bsum *= 719;
bsum += 0x040000;
bsum >>= 19;
}
/*rsum/=729;
rsum<<=8;
gsum/=729;
gsum<<=5;
bsum<<=4;
bsum+=729;
bsum/=1458;
rsum+=0x008000;
gsum+=0x000080;
if(rsum>0xFF0000) rsum=0xFF0000;
if(gsum>0x00FF00) gsum=0x00FF00;
if(bsum>0x0000FF) bsum=0x0000FF;*/
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
}
{
gambatte::uint_least32_t rsum = sums[1].r * 9;
gambatte::uint_least32_t gsum = sums[1].g * 9;
gambatte::uint_least32_t bsum = sums[1].b * 9;
rsum -= sums[0].r;
gsum -= sums[0].g;
bsum -= sums[0].b;
rsum += sums[2].r * 21;
gsum += sums[2].g * 21;
bsum += sums[2].b * 21;
rsum -= sums[3].r << 1;
gsum -= sums[3].g << 1;
bsum -= sums[3].b << 1;
if (rsum & 0x80000000)
rsum = 0;
else if (rsum > 185578)
rsum = 0xFF0000;
else {
rsum *= 719;
rsum >>= 3;
rsum += 0x008000;
rsum &= 0xFF0000;
}
if (gsum & 0x80000000)
gsum = 0;
else if (gsum > 47508223)
gsum = 0xFF00;
else {
gsum >>= 8;
gsum *= 719;
gsum >>= 11;
gsum += 0x000080;
gsum &= 0x00FF00;
}
if (bsum & 0x80000000)
bsum = 0;
else if (bsum > 185578)
bsum = 0x0000FF;
else {
bsum *= 719;
bsum += 0x040000;
bsum >>= 19;
}
/*rsum/=729;
rsum<<=8;
gsum/=729;
gsum<<=5;
bsum<<=4;
bsum+=729;
bsum/=1458;
rsum+=0x008000;
gsum+=0x000080;
if(rsum>0xFF0000) rsum=0xFF0000;
if(gsum>0x00FF00) gsum=0x00FF00;
if(bsum>0x0000FF) bsum=0x0000FF;*/
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
}
++sums;
}
}
static void filter(gambatte::uint_least32_t *dline, const int pitch, const gambatte::uint_least32_t *sline) {
Colorsum sums[PITCH];
for (unsigned h = HEIGHT; h--;) {
{
const gambatte::uint_least32_t *s = sline;
Colorsum *sum = sums;
unsigned n = PITCH;
while (n--) {
const unsigned long pixel = *s;
sum->r = (pixel >> 16) * 27;
sum->g = (pixel & 0x00FF00) * 27;
sum->b = (pixel & 0x0000FF) * 27;
++s;
++sum;
}
}
merge_columns(dline, sums);
dline += pitch;
{
const gambatte::uint_least32_t *s = sline;
Colorsum *sum = sums;
unsigned n = PITCH;
while (n--) {
unsigned long pixel = *s;
unsigned long rsum = (pixel >> 16) * 21;
unsigned long gsum = (pixel & 0x00FF00) * 21;
unsigned long bsum = (pixel & 0x0000FF) * 21;
pixel = s[-1 * PITCH];
rsum -= (pixel >> 16) << 1;
pixel <<= 1;
gsum -= pixel & 0x01FE00;
bsum -= pixel & 0x0001FE;
pixel = s[1 * PITCH];
rsum += (pixel >> 16) * 9;
gsum += (pixel & 0x00FF00) * 9;
bsum += (pixel & 0x0000FF) * 9;
pixel = s[2 * PITCH];
rsum -= pixel >> 16;
gsum -= pixel & 0x00FF00;
bsum -= pixel & 0x0000FF;
sum->r = rsum;
sum->g = gsum;
sum->b = bsum;
++s;
++sum;
}
}
merge_columns(dline, sums);
dline += pitch;
{
const gambatte::uint_least32_t *s = sline;
Colorsum *sum = sums;
unsigned n = PITCH;
while (n--) {
unsigned long pixel = *s;
unsigned long rsum = (pixel >> 16) * 9;
unsigned long gsum = (pixel & 0x00FF00) * 9;
unsigned long bsum = (pixel & 0x0000FF) * 9;
pixel = s[-1 * PITCH];
rsum -= pixel >> 16;
gsum -= pixel & 0x00FF00;
bsum -= pixel & 0x0000FF;
pixel = s[1 * PITCH];
rsum += (pixel >> 16) * 21;
gsum += (pixel & 0x00FF00) * 21;
bsum += (pixel & 0x0000FF) * 21;
pixel = s[2 * PITCH];
rsum -= (pixel >> 16) << 1;
pixel <<= 1;
gsum -= pixel & 0x01FE00;
bsum -= pixel & 0x0001FE;
sum->r = rsum;
sum->g = gsum;
sum->b = bsum;
++s;
++sum;
}
}
merge_columns(dline, sums);
dline += pitch;
sline += PITCH;
}
}
}
Catrom3x::Catrom3x()
: buffer_((HEIGHT + 3UL) * PITCH)
{
std::fill_n(buffer_.get(), buffer_.size(), 0);
}
void* Catrom3x::inBuf() const {
return buffer_ + PITCH + 1;
}
int Catrom3x::inPitch() const {
return PITCH;
}
void Catrom3x::draw(void *const dbuffer, const int pitch) {
::filter(static_cast<gambatte::uint_least32_t*>(dbuffer), pitch, buffer_ + PITCH);
}

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef CATROM3X_H
#define CATROM3X_H
#include "../videolink.h"
#include "../vfilterinfo.h"
#include "gambatte-array.h"
#include "gbint.h"
class Catrom3x : public VideoLink {
const Array<gambatte::uint_least32_t> buffer_;
public:
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 3 };
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 3 };
Catrom3x();
virtual void* inBuf() const;
virtual int inPitch() const;
virtual void draw(void *dst, int dstpitch);
};
#endif

View File

@ -1,234 +0,0 @@
/***************************************************************************
* Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* Copyright (C) 1999 Derek Liauw Kie Fa (Kreed) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "kreed2xsai.h"
#include <algorithm>
namespace {
static inline int getResult1(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) {
int x = 0;
int y = 0;
int r = 0;
if (a == c) ++x;
else if (b == c) ++y;
if (a == d) ++x;
else if (b == d) ++y;
if (x <= 1) ++r;
if (y <= 1) --r;
return r;
}
static inline int getResult2(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) {
int x = 0;
int y = 0;
int r = 0;
if (a == c) ++x;
else if (b == c) ++y;
if (a == d) ++x;
else if (b == d) ++y;
if (x <= 1) --r;
if (y <= 1) ++r;
return r;
}
static inline unsigned long interpolate(const unsigned long a, const unsigned long b) {
return (a + b - ((a ^ b) & 0x010101)) >> 1;
}
static inline unsigned long qInterpolate(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) {
const unsigned long lowBits = ((a & 0x030303) + (b & 0x030303) + (c & 0x030303) + (d & 0x030303)) & 0x030303;
return (a + b + c + d - lowBits) >> 2;
}
template<unsigned srcPitch, unsigned width, unsigned height>
static void filter(gambatte::uint_least32_t *dstPtr, const int dstPitch, const gambatte::uint_least32_t *srcPtr)
{
unsigned h = height;
while (h--) {
const gambatte::uint_least32_t *bP = srcPtr;
gambatte::uint_least32_t *dP = dstPtr;
for (unsigned finish = width; finish--;) {
register unsigned long colorA, colorB;
unsigned long colorC, colorD,
colorE, colorF, colorG, colorH,
colorI, colorJ, colorK, colorL,
colorM, colorN, colorO, colorP;
unsigned long product, product1, product2;
//---------------------------------------
// Map of the pixels: I|E F|J
// G|A B|K
// H|C D|L
// M|N O|P
colorI = *(bP - srcPitch - 1);
colorE = *(bP - srcPitch);
colorF = *(bP - srcPitch + 1);
colorJ = *(bP - srcPitch + 2);
colorG = *(bP - 1);
colorA = *(bP);
colorB = *(bP + 1);
colorK = *(bP + 2);
colorH = *(bP + srcPitch - 1);
colorC = *(bP + srcPitch);
colorD = *(bP + srcPitch + 1);
colorL = *(bP + srcPitch + 2);
colorM = *(bP + srcPitch * 2 - 1);
colorN = *(bP + srcPitch * 2);
colorO = *(bP + srcPitch * 2 + 1);
colorP = *(bP + srcPitch * 2 + 2);
if (colorA == colorD && colorB != colorC) {
if ((colorA == colorE && colorB == colorL) ||
(colorA == colorC && colorA == colorF
&& colorB != colorE && colorB == colorJ)) {
product = colorA;
} else {
product = interpolate(colorA, colorB);
}
if ((colorA == colorG && colorC == colorO) ||
(colorA == colorB && colorA == colorH
&& colorG != colorC && colorC == colorM)) {
product1 = colorA;
} else {
product1 = interpolate(colorA, colorC);
}
product2 = colorA;
} else if (colorB == colorC && colorA != colorD) {
if ((colorB == colorF && colorA == colorH) ||
(colorB == colorE && colorB == colorD
&& colorA != colorF && colorA == colorI)) {
product = colorB;
} else {
product = interpolate(colorA, colorB);
}
if ((colorC == colorH && colorA == colorF) ||
(colorC == colorG && colorC == colorD
&& colorA != colorH && colorA == colorI)) {
product1 = colorC;
} else {
product1 = interpolate(colorA, colorC);
}
product2 = colorB;
} else if (colorA == colorD && colorB == colorC) {
if (colorA == colorB) {
product = colorA;
product1 = colorA;
product2 = colorA;
} else {
register int r = 0;
product1 = interpolate(colorA, colorC);
product = interpolate(colorA, colorB);
r += getResult1(colorA, colorB, colorG, colorE);
r += getResult2(colorB, colorA, colorK, colorF);
r += getResult2(colorB, colorA, colorH, colorN);
r += getResult1(colorA, colorB, colorL, colorO);
if (r > 0)
product2 = colorA;
else if (r < 0)
product2 = colorB;
else {
product2 = qInterpolate(colorA, colorB, colorC, colorD);
}
}
} else {
product2 = qInterpolate(colorA, colorB, colorC, colorD);
if (colorA == colorC && colorA == colorF
&& colorB != colorE && colorB == colorJ) {
product = colorA;
} else if (colorB == colorE && colorB == colorD
&& colorA != colorF && colorA == colorI) {
product = colorB;
} else {
product = interpolate(colorA, colorB);
}
if (colorA == colorB && colorA == colorH
&& colorG != colorC && colorC == colorM) {
product1 = colorA;
} else if (colorC == colorG && colorC == colorD
&& colorA != colorH && colorA == colorI) {
product1 = colorC;
} else {
product1 = interpolate(colorA, colorC);
}
}
*dP = colorA;
*(dP + 1) = product;
*(dP + dstPitch) = product1;
*(dP + dstPitch + 1) = product2;
++bP;
dP += 2;
}
srcPtr += srcPitch;
dstPtr += dstPitch * 2;
}
}
enum { WIDTH = VfilterInfo::IN_WIDTH };
enum { HEIGHT = VfilterInfo::IN_HEIGHT };
enum { PITCH = WIDTH + 3 };
enum { BUF_SIZE = (HEIGHT + 3) * PITCH };
enum { BUF_OFFSET = PITCH + 1 };
}
Kreed2xSaI::Kreed2xSaI()
: buffer_(BUF_SIZE)
{
std::fill_n(buffer_.get(), buffer_.size(), 0);
}
void* Kreed2xSaI::inBuf() const {
return buffer_ + BUF_OFFSET;
}
int Kreed2xSaI::inPitch() const {
return PITCH;
}
void Kreed2xSaI::draw(void *const dbuffer, const int pitch) {
::filter<PITCH, WIDTH, HEIGHT>(static_cast<gambatte::uint_least32_t*>(dbuffer), pitch, buffer_ + BUF_OFFSET);
}

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef KREED2XSAI_H
#define KREED2XSAI_H
#include "../videolink.h"
#include "../vfilterinfo.h"
#include "gambatte-array.h"
#include "gbint.h"
class Kreed2xSaI : public VideoLink {
const Array<gambatte::uint_least32_t> buffer_;
public:
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
Kreed2xSaI();
virtual void* inBuf() const;
virtual int inPitch() const;
virtual void draw(void *dst, int dstpitch);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef MAXSTHQ2X_H
#define MAXSTHQ2X_H
#include "../videolink.h"
#include "../vfilterinfo.h"
#include "gambatte-array.h"
#include "gbint.h"
class MaxStHq2x : public VideoLink {
const Array<gambatte::uint_least32_t> buffer_;
public:
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 2 };
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 2 };
MaxStHq2x();
virtual void* inBuf() const;
virtual int inPitch() const;
virtual void draw(void *dst, int dstpitch);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef MAXSTHQ3X_H
#define MAXSTHQ3X_H
#include "../videolink.h"
#include "../vfilterinfo.h"
#include "gambatte-array.h"
#include "gbint.h"
class MaxStHq3x : public VideoLink {
const Array<gambatte::uint_least32_t> buffer_;
public:
enum { OUT_WIDTH = VfilterInfo::IN_WIDTH * 3 };
enum { OUT_HEIGHT = VfilterInfo::IN_HEIGHT * 3 };
MaxStHq3x();
virtual void* inBuf() const;
virtual int inPitch() const;
virtual void draw(void *dst, int dstpitch);
};
#endif

View File

@ -1,30 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Sindre Aamås *
* aamas@stud.ntnu.no *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. *
* *
* You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef VIDEOLINK_H
#define VIDEOLINK_H
class VideoLink {
public:
virtual ~VideoLink() {}
virtual void* inBuf() const = 0;
virtual int inPitch() const = 0;
virtual void draw(void *dst, int dstpitch) = 0;
};
#endif