mirror of https://github.com/stella-emu/stella.git
Remove high frequency artifacts from Lanczos resampling.
Run the TIA signal through a high pass with 10Hz cutoff.
This commit is contained in:
parent
8298ad4d26
commit
a4d923cbe6
|
@ -0,0 +1,41 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include <cmath>
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#include "HighPass.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
HighPass::HighPass(float cutOffFrequency, float frequency)
|
||||
: myLastValueIn(0),
|
||||
myLastValueOut(0),
|
||||
myAlpha(1.f / (1.f + 2.f*M_PI*cutOffFrequency/frequency))
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float HighPass::apply(float valueIn)
|
||||
{
|
||||
float valueOut = myAlpha * (myLastValueOut + valueIn - myLastValueIn);
|
||||
|
||||
myLastValueIn = valueIn;
|
||||
myLastValueOut = valueOut;
|
||||
|
||||
return valueOut;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef HIGH_PASS_HXX
|
||||
#define HIGH_PASS_HXX
|
||||
|
||||
class HighPass
|
||||
{
|
||||
public:
|
||||
|
||||
HighPass(float cutOffFrequency, float frequency);
|
||||
|
||||
float apply(float value);
|
||||
|
||||
private:
|
||||
|
||||
float myLastValueIn;
|
||||
|
||||
float myLastValueOut;
|
||||
|
||||
float myAlpha;
|
||||
|
||||
private:
|
||||
|
||||
HighPass() = delete;
|
||||
};
|
||||
|
||||
#endif // HIGH_PASS_HXX
|
|
@ -25,6 +25,7 @@
|
|||
namespace {
|
||||
|
||||
constexpr float CLIPPING_FACTOR = 0.75;
|
||||
constexpr float HIGH_PASS_CUT_OFF = 10;
|
||||
|
||||
uInt32 reducedDenominator(uInt32 n, uInt32 d)
|
||||
{
|
||||
|
@ -78,6 +79,9 @@ LanczosResampler::LanczosResampler(
|
|||
myCurrentFragment(nullptr),
|
||||
myFragmentIndex(0),
|
||||
myIsUnderrun(true),
|
||||
myHighPassL(HIGH_PASS_CUT_OFF, formatFrom.sampleRate),
|
||||
myHighPassR(HIGH_PASS_CUT_OFF, formatFrom.sampleRate),
|
||||
myHighPass(HIGH_PASS_CUT_OFF, formatFrom.sampleRate),
|
||||
myTimeIndex(0)
|
||||
{
|
||||
myPrecomputedKernels = make_unique<float[]>(myPrecomputedKernelCount * myKernelSize);
|
||||
|
@ -184,11 +188,11 @@ inline void LanczosResampler::shiftSamples(uInt32 samplesToShift)
|
|||
{
|
||||
while (samplesToShift-- > 0) {
|
||||
if (myFormatFrom.stereo) {
|
||||
myBufferL->shift(myCurrentFragment[2*myFragmentIndex] / static_cast<float>(0x7fff));
|
||||
myBufferR->shift(myCurrentFragment[2*myFragmentIndex + 1] / static_cast<float>(0x7fff));
|
||||
myBufferL->shift(myHighPassL.apply(myCurrentFragment[2*myFragmentIndex] / static_cast<float>(0x7fff)));
|
||||
myBufferR->shift(myHighPassR.apply(myCurrentFragment[2*myFragmentIndex + 1] / static_cast<float>(0x7fff)));
|
||||
}
|
||||
else
|
||||
myBuffer->shift(myCurrentFragment[myFragmentIndex] / static_cast<float>(0x7fff));
|
||||
myBuffer->shift(myHighPass.apply(myCurrentFragment[myFragmentIndex] / static_cast<float>(0x7fff)));
|
||||
|
||||
myFragmentIndex++;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "bspf.hxx"
|
||||
#include "Resampler.hxx"
|
||||
#include "ConvolutionBuffer.hxx"
|
||||
#include "HighPass.hxx"
|
||||
|
||||
class LanczosResampler : public Resampler
|
||||
{
|
||||
|
@ -59,6 +60,10 @@ class LanczosResampler : public Resampler
|
|||
uInt32 myFragmentIndex;
|
||||
bool myIsUnderrun;
|
||||
|
||||
HighPass myHighPassL;
|
||||
HighPass myHighPassR;
|
||||
HighPass myHighPass;
|
||||
|
||||
uInt32 myTimeIndex;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ MODULE := src/common/audio
|
|||
MODULE_OBJS := \
|
||||
src/common/audio/SimpleResampler.o \
|
||||
src/common/audio/ConvolutionBuffer.o \
|
||||
src/common/audio/LanczosResampler.o
|
||||
src/common/audio/LanczosResampler.o \
|
||||
src/common/audio/HighPass.o
|
||||
|
||||
MODULE_DIRS += \
|
||||
src/emucore/tia
|
||||
|
|
Loading…
Reference in New Issue