mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-26 17:30:23 +00:00
Cleanup more stuff we don't need
This commit is contained in:
parent
281880de9a
commit
440e49b83d
@ -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)
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "cd libgambatte && scons"
|
||||
(cd libgambatte && scons) || exit
|
||||
|
||||
echo "cd gambatte_sdl && scons"
|
||||
(cd gambatte_sdl && scons)
|
16
clean.sh
16
clean.sh
@ -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*
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
@ -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);
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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];
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
@ -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
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user