mirror of https://github.com/probonopd/MiniDexed
parent
bf30d1a1c9
commit
6d673aa8be
@ -0,0 +1,116 @@ |
||||
/*
|
||||
* MVerb Reverb Port |
||||
* Ported from https://github.com/DISTRHO/MVerb
|
||||
* Original https://github.com/martineastwood/mverb/
|
||||
* |
||||
* Javier Nonis (https://github.com/jnonis) - 2024
|
||||
*/ |
||||
#include "effect_mverb.h" |
||||
|
||||
AudioEffectMVerb::AudioEffectMVerb(float32_t samplerate) : AudioEffect(samplerate) |
||||
{
|
||||
fVerb.setSampleRate(samplerate); |
||||
|
||||
fVerb.setParameter(MVerb<float>::DAMPINGFREQ, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::DENSITY, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::BANDWIDTHFREQ, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::DECAY, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::PREDELAY, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::SIZE, 0.75f); |
||||
fVerb.setParameter(MVerb<float>::GAIN, 1.0f); |
||||
fVerb.setParameter(MVerb<float>::MIX, 0.5f); |
||||
fVerb.setParameter(MVerb<float>::EARLYMIX, 0.5f); |
||||
fVerb.reset(); |
||||
} |
||||
|
||||
AudioEffectMVerb::~AudioEffectMVerb() |
||||
{ |
||||
} |
||||
|
||||
void AudioEffectMVerb::initializeSendFX() |
||||
{ |
||||
this->setParameter(AudioEffectMVerb::Param::MIX, 100); |
||||
} |
||||
|
||||
void AudioEffectMVerb::setParameter(unsigned param, unsigned value) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectMVerb::Param::BYPASS: |
||||
this->setBypass(value == 1); |
||||
break; |
||||
case AudioEffectMVerb::Param::DAMPINGFREQ: |
||||
fVerb.setParameter(MVerb<float>::DAMPINGFREQ, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::DENSITY: |
||||
fVerb.setParameter(MVerb<float>::DENSITY, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::BANDWIDTHFREQ: |
||||
fVerb.setParameter(MVerb<float>::BANDWIDTHFREQ, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::DECAY: |
||||
fVerb.setParameter(MVerb<float>::DECAY, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::PREDELAY: |
||||
fVerb.setParameter(MVerb<float>::PREDELAY, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::SIZE: |
||||
fVerb.setParameter(MVerb<float>::SIZE, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::GAIN: |
||||
fVerb.setParameter(MVerb<float>::GAIN, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::MIX: |
||||
fVerb.setParameter(MVerb<float>::MIX, (float) value / 100.0f); |
||||
break; |
||||
case AudioEffectMVerb::Param::EARLYMIX: |
||||
fVerb.setParameter(MVerb<float>::EARLYMIX, (float) value / 100.0f); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
unsigned AudioEffectMVerb::getParameter(unsigned param) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectMVerb::Param::BYPASS: |
||||
return this->getBypass() ? 1 : 0; |
||||
case AudioEffectMVerb::Param::DAMPINGFREQ: |
||||
return roundf(fVerb.getParameter(MVerb<float>::DAMPINGFREQ) * 100); |
||||
case AudioEffectMVerb::Param::DENSITY: |
||||
return roundf(fVerb.getParameter(MVerb<float>::DENSITY) * 100); |
||||
case AudioEffectMVerb::Param::BANDWIDTHFREQ: |
||||
return roundf(fVerb.getParameter(MVerb<float>::BANDWIDTHFREQ) * 100); |
||||
case AudioEffectMVerb::Param::DECAY: |
||||
return roundf(fVerb.getParameter(MVerb<float>::DECAY) * 100); |
||||
case AudioEffectMVerb::Param::PREDELAY: |
||||
return roundf(fVerb.getParameter(MVerb<float>::PREDELAY) * 100); |
||||
case AudioEffectMVerb::Param::SIZE: |
||||
return roundf(fVerb.getParameter(MVerb<float>::SIZE) * 100); |
||||
case AudioEffectMVerb::Param::GAIN: |
||||
return roundf(fVerb.getParameter(MVerb<float>::GAIN) * 100); |
||||
case AudioEffectMVerb::Param::MIX: |
||||
return roundf(fVerb.getParameter(MVerb<float>::MIX) * 100); |
||||
case AudioEffectMVerb::Param::EARLYMIX: |
||||
return roundf(fVerb.getParameter(MVerb<float>::EARLYMIX) * 100); |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
void AudioEffectMVerb::doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) |
||||
{ |
||||
const float32_t* inputs[2]; |
||||
inputs[0] = inblockL; |
||||
inputs[1] = inblockR; |
||||
|
||||
float32_t* outputs[2]; |
||||
outputs[0] = outblockL; |
||||
outputs[1] = outblockR; |
||||
|
||||
fVerb.process(inputs, outputs, static_cast<int>(len)); |
||||
} |
||||
|
@ -0,0 +1,54 @@ |
||||
/*
|
||||
* MVerb Reverb Port |
||||
* Ported from https://github.com/DISTRHO/MVerb
|
||||
* Original https://github.com/martineastwood/mverb/
|
||||
* |
||||
* Javier Nonis (https://github.com/jnonis) - 2024
|
||||
*/ |
||||
#ifndef _EFFECT_MVERB_H |
||||
#define _EFFECT_MVERB_H |
||||
|
||||
#include "effect_base.h" |
||||
#include "mverb/MVerb.h" |
||||
|
||||
class AudioEffectMVerb : public AudioEffect |
||||
{ |
||||
public: |
||||
enum Param |
||||
{ |
||||
BYPASS, |
||||
DAMPINGFREQ, |
||||
DENSITY, |
||||
BANDWIDTHFREQ, |
||||
DECAY, |
||||
PREDELAY, |
||||
SIZE, |
||||
GAIN, |
||||
MIX, |
||||
EARLYMIX, |
||||
UNKNOWN |
||||
}; |
||||
|
||||
AudioEffectMVerb(float32_t samplerate); |
||||
virtual ~AudioEffectMVerb(); |
||||
|
||||
virtual unsigned getId() |
||||
{ |
||||
return EFFECT_MVERB; |
||||
} |
||||
|
||||
virtual void initializeSendFX(); |
||||
virtual void setParameter(unsigned param, unsigned value); |
||||
virtual unsigned getParameter(unsigned param); |
||||
protected: |
||||
virtual size_t getParametersSize() |
||||
{ |
||||
return AudioEffectMVerb::Param::UNKNOWN; |
||||
} |
||||
virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len); |
||||
|
||||
private: |
||||
MVerb<float> fVerb; |
||||
}; |
||||
|
||||
#endif // _EFFECT_MVERB_H
|
@ -0,0 +1,842 @@ |
||||
// Copyright (c) 2010 Martin Eastwood
|
||||
// This code is distributed under the terms of the GNU General Public License
|
||||
|
||||
// MVerb is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// at your option) any later version.
|
||||
//
|
||||
// MVerb 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 for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this MVerb. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _EMVERB_H |
||||
#define _EMVERB_H |
||||
|
||||
#include <cmath> |
||||
#include <cstring> |
||||
|
||||
//forward declaration
|
||||
template<typename T, int maxLength> class Allpass; |
||||
template<typename T, int maxLength> class StaticAllpassFourTap; |
||||
template<typename T, int maxLength> class StaticDelayLine; |
||||
template<typename T, int maxLength> class StaticDelayLineFourTap; |
||||
template<typename T, int maxLength> class StaticDelayLineEightTap; |
||||
template<typename T, int OverSampleCount> class StateVariable; |
||||
|
||||
template<typename T> |
||||
class MVerb |
||||
{ |
||||
private: |
||||
Allpass<T, 96000> allpass[4]; |
||||
StaticAllpassFourTap<T, 96000> allpassFourTap[4]; |
||||
StateVariable<T,4> bandwidthFilter[2]; |
||||
StateVariable<T,4> damping[2]; |
||||
StaticDelayLine<T, 96000> predelay; |
||||
StaticDelayLineFourTap<T, 96000> staticDelayLine[4]; |
||||
StaticDelayLineEightTap<T, 96000> earlyReflectionsDelayLine[2]; |
||||
T SampleRate, DampingFreq, Density1, Density2, BandwidthFreq, PreDelayTime, Decay, Gain, Mix, EarlyMix, Size; |
||||
T MixSmooth, EarlyLateSmooth, BandwidthSmooth, DampingSmooth, PredelaySmooth, SizeSmooth, DensitySmooth, DecaySmooth; |
||||
T PreviousLeftTank, PreviousRightTank; |
||||
int ControlRate, ControlRateCounter; |
||||
|
||||
public: |
||||
enum |
||||
{ |
||||
DAMPINGFREQ=0, |
||||
DENSITY, |
||||
BANDWIDTHFREQ, |
||||
DECAY, |
||||
PREDELAY, |
||||
SIZE, |
||||
GAIN, |
||||
MIX, |
||||
EARLYMIX, |
||||
NUM_PARAMS |
||||
}; |
||||
|
||||
MVerb(){ |
||||
DampingFreq = 0.9; |
||||
BandwidthFreq = 0.9; |
||||
SampleRate = 44100.; |
||||
Decay = 0.5; |
||||
Gain = 1.; |
||||
Mix = 1.; |
||||
Size = 1.; |
||||
EarlyMix = 1.; |
||||
PreviousLeftTank = 0.; |
||||
PreviousRightTank = 0.; |
||||
PreDelayTime = 100 * (SampleRate / 1000); |
||||
MixSmooth = EarlyLateSmooth = BandwidthSmooth = DampingSmooth = PredelaySmooth = SizeSmooth = DecaySmooth = DensitySmooth = 0.; |
||||
ControlRate = SampleRate / 1000; |
||||
ControlRateCounter = 0; |
||||
reset(); |
||||
} |
||||
|
||||
~MVerb(){ |
||||
//nowt to do here
|
||||
} |
||||
|
||||
void process(const T **inputs, T **outputs, int sampleFrames){ |
||||
T OneOverSampleFrames = 1. / sampleFrames; |
||||
T MixDelta = (Mix - MixSmooth) * OneOverSampleFrames; |
||||
T EarlyLateDelta = (EarlyMix - EarlyLateSmooth) * OneOverSampleFrames; |
||||
T BandwidthDelta = (((BandwidthFreq * 18400.) + 100.) - BandwidthSmooth) * OneOverSampleFrames; |
||||
T DampingDelta = (((DampingFreq * 18400.) + 100.) - DampingSmooth) * OneOverSampleFrames; |
||||
T PredelayDelta = ((PreDelayTime * 200 * (SampleRate / 1000)) - PredelaySmooth) * OneOverSampleFrames; |
||||
T SizeDelta = (Size - SizeSmooth) * OneOverSampleFrames; |
||||
T DecayDelta = (((0.7995f * Decay) + 0.005) - DecaySmooth) * OneOverSampleFrames; |
||||
T DensityDelta = (((0.7995f * Density1) + 0.005) - DensitySmooth) * OneOverSampleFrames; |
||||
for(int i=0;i<sampleFrames;++i){ |
||||
T left = inputs[0][i]; |
||||
T right = inputs[1][i]; |
||||
MixSmooth += MixDelta; |
||||
EarlyLateSmooth += EarlyLateDelta; |
||||
BandwidthSmooth += BandwidthDelta; |
||||
DampingSmooth += DampingDelta; |
||||
PredelaySmooth += PredelayDelta; |
||||
SizeSmooth += SizeDelta; |
||||
DecaySmooth += DecayDelta; |
||||
DensitySmooth += DensityDelta; |
||||
if (ControlRateCounter >= ControlRate){ |
||||
ControlRateCounter = 0; |
||||
bandwidthFilter[0].Frequency(BandwidthSmooth); |
||||
bandwidthFilter[1].Frequency(BandwidthSmooth); |
||||
damping[0].Frequency(DampingSmooth); |
||||
damping[1].Frequency(DampingSmooth); |
||||
} |
||||
++ControlRateCounter; |
||||
predelay.SetLength(PredelaySmooth); |
||||
Density2 = DecaySmooth + 0.15; |
||||
if (Density2 > 0.5) |
||||
Density2 = 0.5; |
||||
if (Density2 < 0.25) |
||||
Density2 = 0.25; |
||||
allpassFourTap[1].SetFeedback(Density2); |
||||
allpassFourTap[3].SetFeedback(Density2); |
||||
allpassFourTap[0].SetFeedback(Density1); |
||||
allpassFourTap[2].SetFeedback(Density1); |
||||
T bandwidthLeft = bandwidthFilter[0](left) ; |
||||
T bandwidthRight = bandwidthFilter[1](right) ; |
||||
T earlyReflectionsL = earlyReflectionsDelayLine[0] ( bandwidthLeft * 0.5 + bandwidthRight * 0.3 ) |
||||
+ earlyReflectionsDelayLine[0].GetIndex(2) * 0.6 |
||||
+ earlyReflectionsDelayLine[0].GetIndex(3) * 0.4 |
||||
+ earlyReflectionsDelayLine[0].GetIndex(4) * 0.3 |
||||
+ earlyReflectionsDelayLine[0].GetIndex(5) * 0.3 |
||||
+ earlyReflectionsDelayLine[0].GetIndex(6) * 0.1 |
||||
+ earlyReflectionsDelayLine[0].GetIndex(7) * 0.1 |
||||
+ ( bandwidthLeft * 0.4 + bandwidthRight * 0.2 ) * 0.5 ; |
||||
T earlyReflectionsR = earlyReflectionsDelayLine[1] ( bandwidthLeft * 0.3 + bandwidthRight * 0.5 ) |
||||
+ earlyReflectionsDelayLine[1].GetIndex(2) * 0.6 |
||||
+ earlyReflectionsDelayLine[1].GetIndex(3) * 0.4 |
||||
+ earlyReflectionsDelayLine[1].GetIndex(4) * 0.3 |
||||
+ earlyReflectionsDelayLine[1].GetIndex(5) * 0.3 |
||||
+ earlyReflectionsDelayLine[1].GetIndex(6) * 0.1 |
||||
+ earlyReflectionsDelayLine[1].GetIndex(7) * 0.1 |
||||
+ ( bandwidthLeft * 0.2 + bandwidthRight * 0.4 ) * 0.5 ; |
||||
T predelayMonoInput = predelay(( bandwidthRight + bandwidthLeft ) * 0.5f); |
||||
T smearedInput = predelayMonoInput; |
||||
for(int j=0;j<4;j++) |
||||
smearedInput = allpass[j] ( smearedInput ); |
||||
T leftTank = allpassFourTap[0] ( smearedInput + PreviousRightTank ) ; |
||||
leftTank = staticDelayLine[0] (leftTank); |
||||
leftTank = damping[0](leftTank); |
||||
leftTank = allpassFourTap[1](leftTank); |
||||
leftTank = staticDelayLine[1](leftTank); |
||||
T rightTank = allpassFourTap[2] (smearedInput + PreviousLeftTank) ; |
||||
rightTank = staticDelayLine[2](rightTank); |
||||
rightTank = damping[1] (rightTank); |
||||
rightTank = allpassFourTap[3](rightTank); |
||||
rightTank = staticDelayLine[3](rightTank); |
||||
PreviousLeftTank = leftTank * DecaySmooth; |
||||
PreviousRightTank = rightTank * DecaySmooth; |
||||
T accumulatorL = (0.6*staticDelayLine[2].GetIndex(1)) |
||||
+(0.6*staticDelayLine[2].GetIndex(2)) |
||||
-(0.6*allpassFourTap[3].GetIndex(1)) |
||||
+(0.6*staticDelayLine[3].GetIndex(1)) |
||||
-(0.6*staticDelayLine[0].GetIndex(1)) |
||||
-(0.6*allpassFourTap[1].GetIndex(1)) |
||||
-(0.6*staticDelayLine[1].GetIndex(1)); |
||||
T accumulatorR = (0.6*staticDelayLine[0].GetIndex(2)) |
||||
+(0.6*staticDelayLine[0].GetIndex(3)) |
||||
-(0.6*allpassFourTap[1].GetIndex(2)) |
||||
+(0.6*staticDelayLine[1].GetIndex(2)) |
||||
-(0.6*staticDelayLine[2].GetIndex(3)) |
||||
-(0.6*allpassFourTap[3].GetIndex(2)) |
||||
-(0.6*staticDelayLine[3].GetIndex(2)); |
||||
accumulatorL = ((accumulatorL * EarlyMix) + ((1 - EarlyMix) * earlyReflectionsL)); |
||||
accumulatorR = ((accumulatorR * EarlyMix) + ((1 - EarlyMix) * earlyReflectionsR)); |
||||
left = ( left + MixSmooth * ( accumulatorL - left ) ) * Gain; |
||||
right = ( right + MixSmooth * ( accumulatorR - right ) ) * Gain; |
||||
outputs[0][i] = left; |
||||
outputs[1][i] = right; |
||||
} |
||||
} |
||||
|
||||
void reset(){ |
||||
ControlRateCounter = 0; |
||||
bandwidthFilter[0].SetSampleRate (SampleRate ); |
||||
bandwidthFilter[1].SetSampleRate (SampleRate ); |
||||
bandwidthFilter[0].Reset(); |
||||
bandwidthFilter[1].Reset(); |
||||
damping[0].SetSampleRate (SampleRate ); |
||||
damping[1].SetSampleRate (SampleRate ); |
||||
damping[0].Reset(); |
||||
damping[1].Reset(); |
||||
predelay.Clear(); |
||||
predelay.SetLength(PreDelayTime); |
||||
allpass[0].Clear(); |
||||
allpass[1].Clear(); |
||||
allpass[2].Clear(); |
||||
allpass[3].Clear(); |
||||
allpass[0].SetLength (0.0048 * SampleRate); |
||||
allpass[1].SetLength (0.0036 * SampleRate); |
||||
allpass[2].SetLength (0.0127 * SampleRate); |
||||
allpass[3].SetLength (0.0093 * SampleRate); |
||||
allpass[0].SetFeedback (0.75); |
||||
allpass[1].SetFeedback (0.75); |
||||
allpass[2].SetFeedback (0.625); |
||||
allpass[3].SetFeedback (0.625); |
||||
allpassFourTap[0].Clear(); |
||||
allpassFourTap[1].Clear(); |
||||
allpassFourTap[2].Clear(); |
||||
allpassFourTap[3].Clear(); |
||||
allpassFourTap[0].SetLength(0.020 * SampleRate * Size); |
||||
allpassFourTap[1].SetLength(0.060 * SampleRate * Size); |
||||
allpassFourTap[2].SetLength(0.030 * SampleRate * Size); |
||||
allpassFourTap[3].SetLength(0.089 * SampleRate * Size); |
||||
allpassFourTap[0].SetFeedback(Density1); |
||||
allpassFourTap[1].SetFeedback(Density2); |
||||
allpassFourTap[2].SetFeedback(Density1); |
||||
allpassFourTap[3].SetFeedback(Density2); |
||||
allpassFourTap[0].SetIndex(0,0,0,0); |
||||
allpassFourTap[1].SetIndex(0,0.006 * SampleRate * Size, 0.041 * SampleRate * Size, 0); |
||||
allpassFourTap[2].SetIndex(0,0,0,0); |
||||
allpassFourTap[3].SetIndex(0,0.031 * SampleRate * Size, 0.011 * SampleRate * Size, 0); |
||||
staticDelayLine[0].Clear(); |
||||
staticDelayLine[1].Clear(); |
||||
staticDelayLine[2].Clear(); |
||||
staticDelayLine[3].Clear(); |
||||
staticDelayLine[0].SetLength(0.15 * SampleRate * Size); |
||||
staticDelayLine[1].SetLength(0.12 * SampleRate * Size); |
||||
staticDelayLine[2].SetLength(0.14 * SampleRate * Size); |
||||
staticDelayLine[3].SetLength(0.11 * SampleRate * Size); |
||||
staticDelayLine[0].SetIndex(0, 0.067 * SampleRate * Size, 0.011 * SampleRate * Size , 0.121 * SampleRate * Size); |
||||
staticDelayLine[1].SetIndex(0, 0.036 * SampleRate * Size, 0.089 * SampleRate * Size , 0); |
||||
staticDelayLine[2].SetIndex(0, 0.0089 * SampleRate * Size, 0.099 * SampleRate * Size , 0); |
||||
staticDelayLine[3].SetIndex(0, 0.067 * SampleRate * Size, 0.0041 * SampleRate * Size , 0); |
||||
earlyReflectionsDelayLine[0].Clear(); |
||||
earlyReflectionsDelayLine[1].Clear(); |
||||
earlyReflectionsDelayLine[0].SetLength(0.089 * SampleRate); |
||||
earlyReflectionsDelayLine[0].SetIndex (0, 0.0199*SampleRate, 0.0219*SampleRate, 0.0354*SampleRate,0.0389*SampleRate, 0.0414*SampleRate, 0.0692*SampleRate, 0); |
||||
earlyReflectionsDelayLine[1].SetLength(0.069 * SampleRate); |
||||
earlyReflectionsDelayLine[1].SetIndex (0, 0.0099*SampleRate, 0.011*SampleRate, 0.0182*SampleRate,0.0189*SampleRate, 0.0213*SampleRate, 0.0431*SampleRate, 0); |
||||
} |
||||
|
||||
void setParameter(int index, T value){ |
||||
switch(index){ |
||||
case DAMPINGFREQ: |
||||
DampingFreq = /* 1. - */ value; // FIXME?
|
||||
break; |
||||
case DENSITY: |
||||
Density1 = value; |
||||
break; |
||||
case BANDWIDTHFREQ: |
||||
BandwidthFreq = value; |
||||
break; |
||||
case PREDELAY: |
||||
PreDelayTime = value; |
||||
break; |
||||
case SIZE: |
||||
Size = value; |
||||
allpassFourTap[0].Clear(); |
||||
allpassFourTap[1].Clear(); |
||||
allpassFourTap[2].Clear(); |
||||
allpassFourTap[3].Clear(); |
||||
allpassFourTap[0].SetLength(0.020 * SampleRate * Size); |
||||
allpassFourTap[1].SetLength(0.060 * SampleRate * Size); |
||||
allpassFourTap[2].SetLength(0.030 * SampleRate * Size); |
||||
allpassFourTap[3].SetLength(0.089 * SampleRate * Size); |
||||
allpassFourTap[1].SetIndex(0,0.006 * SampleRate * Size, 0.041 * SampleRate * Size, 0); |
||||
allpassFourTap[3].SetIndex(0,0.031 * SampleRate * Size, 0.011 * SampleRate * Size, 0); |
||||
staticDelayLine[0].Clear(); |
||||
staticDelayLine[1].Clear(); |
||||
staticDelayLine[2].Clear(); |
||||
staticDelayLine[3].Clear(); |
||||
staticDelayLine[0].SetLength(0.15 * SampleRate * Size); |
||||
staticDelayLine[1].SetLength(0.12 * SampleRate * Size); |
||||
staticDelayLine[2].SetLength(0.14 * SampleRate * Size); |
||||
staticDelayLine[3].SetLength(0.11 * SampleRate * Size); |
||||
staticDelayLine[0].SetIndex(0, 0.067 * SampleRate * Size, 0.011 * SampleRate * Size , 0.121 * SampleRate * Size); |
||||
staticDelayLine[1].SetIndex(0, 0.036 * SampleRate * Size, 0.089 * SampleRate * Size , 0); |
||||
staticDelayLine[2].SetIndex(0, 0.0089 * SampleRate * Size, 0.099 * SampleRate * Size , 0); |
||||
staticDelayLine[3].SetIndex(0, 0.067 * SampleRate * Size, 0.0041 * SampleRate * Size , 0); |
||||
break; |
||||
case DECAY: |
||||
Decay = value; |
||||
break; |
||||
case GAIN: |
||||
Gain = value; |
||||
break; |
||||
case MIX: |
||||
Mix = value; |
||||
break; |
||||
case EARLYMIX: |
||||
EarlyMix = value; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
float getParameter(int index) const{ |
||||
switch(index){ |
||||
case DAMPINGFREQ: |
||||
return DampingFreq; |
||||
break; |
||||
case DENSITY: |
||||
return Density1; |
||||
break; |
||||
case BANDWIDTHFREQ: |
||||
return BandwidthFreq; |
||||
break; |
||||
case PREDELAY: |
||||
return PreDelayTime; |
||||
break; |
||||
case SIZE: |
||||
return Size; |
||||
break; |
||||
case DECAY: |
||||
return Decay; |
||||
break; |
||||
case GAIN: |
||||
return Gain; |
||||
break; |
||||
case MIX: |
||||
return Mix; |
||||
break; |
||||
case EARLYMIX: |
||||
return EarlyMix; |
||||
break; |
||||
default: return 0.f; |
||||
break; |
||||
|
||||
} |
||||
} |
||||
|
||||
void setSampleRate(T sr){ |
||||
SampleRate = sr; |
||||
ControlRate = SampleRate / 1000; |
||||
reset(); |
||||
} |
||||
}; |
||||
|
||||
|
||||
|
||||
template<typename T, int maxLength> |
||||
class Allpass |
||||
{ |
||||
private: |
||||
T buffer[maxLength]; |
||||
int index; |
||||
int Length; |
||||
T Feedback; |
||||
|
||||
public: |
||||
Allpass() |
||||
{ |
||||
SetLength ( maxLength - 1 ); |
||||
Clear(); |
||||
Feedback = 0.5; |
||||
} |
||||
|
||||
T operator()(T input) |
||||
{ |
||||
T output; |
||||
T bufout; |
||||
bufout = buffer[index]; |
||||
T temp = input * -Feedback; |
||||
output = bufout + temp; |
||||
buffer[index] = input + ((bufout+temp)*Feedback); |
||||
if(++index>=Length) index = 0; |
||||
return output; |
||||
} |
||||
|
||||
void SetLength (int Length) |
||||
{ |
||||
if( Length >= maxLength ) |
||||
Length = maxLength; |
||||
if( Length < 0 ) |
||||
Length = 0; |
||||
|
||||
this->Length = Length; |
||||
} |
||||
|
||||
void SetFeedback(T feedback) |
||||
{ |
||||
Feedback = feedback; |
||||
} |
||||
|
||||
void Clear() |
||||
{ |
||||
std::memset(buffer, 0, sizeof(buffer)); |
||||
index = 0; |
||||
} |
||||
|
||||
int GetLength() const |
||||
{ |
||||
return Length; |
||||
} |
||||
}; |
||||
|
||||
template<typename T, int maxLength> |
||||
class StaticAllpassFourTap |
||||
{ |
||||
private: |
||||
T buffer[maxLength]; |
||||
int index1, index2, index3, index4; |
||||
int Length; |
||||
T Feedback; |
||||
|
||||
public: |
||||
StaticAllpassFourTap() |
||||
{ |
||||
SetLength ( maxLength - 1 ); |
||||
Clear(); |
||||
Feedback = 0.5; |
||||
} |
||||
|
||||
T operator()(T input) |
||||
{ |
||||
T output; |
||||
T bufout; |
||||
|
||||
bufout = buffer[index1]; |
||||
T temp = input * -Feedback; |
||||
output = bufout + temp; |
||||
buffer[index1] = input + ((bufout+temp)*Feedback); |
||||
|
||||
if(++index1>=Length) |
||||
index1 = 0; |
||||
if(++index2 >= Length) |
||||
index2 = 0; |
||||
if(++index3 >= Length) |
||||
index3 = 0; |
||||
if(++index4 >= Length) |
||||
index4 = 0; |
||||
|
||||
return output; |
||||
} |
||||
|
||||
void SetIndex (int Index1, int Index2, int Index3, int Index4) |
||||
{ |
||||
index1 = Index1; |
||||
index2 = Index2; |
||||
index3 = Index3; |
||||
index4 = Index4; |
||||
} |
||||
|
||||
T GetIndex (int Index) |
||||
{ |
||||
switch (Index) |
||||
{ |
||||
case 0: |
||||
return buffer[index1]; |
||||
break; |
||||
case 1: |
||||
return buffer[index2]; |
||||
break; |
||||
case 2: |
||||
return buffer[index3]; |
||||
break; |
||||
case 3: |
||||
return buffer[index4]; |
||||
break; |
||||
default: |
||||
return buffer[index1]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void SetLength (int Length) |
||||
{ |
||||
if( Length >= maxLength ) |
||||
Length = maxLength; |
||||
if( Length < 0 ) |
||||
Length = 0; |
||||
|
||||
this->Length = Length; |
||||
} |
||||
|
||||
|
||||
void Clear() |
||||
{ |
||||
std::memset(buffer, 0, sizeof(buffer)); |
||||
index1 = index2 = index3 = index4 = 0; |
||||
} |
||||
|
||||
void SetFeedback(T feedback) |
||||
{ |
||||
Feedback = feedback; |
||||
} |
||||
|
||||
int GetLength() const |
||||
{ |
||||
return Length; |
||||
} |
||||
}; |
||||
|
||||
template<typename T, int maxLength> |
||||
class StaticDelayLine |
||||
{ |
||||
private: |
||||
T buffer[maxLength]; |
||||
int index; |
||||
int Length; |
||||
T Feedback; |
||||
|
||||
public: |
||||
StaticDelayLine() |
||||
{ |
||||
SetLength ( maxLength - 1 ); |
||||
Clear(); |
||||
} |
||||
|
||||
T operator()(T input) |
||||
{ |
||||
T output = buffer[index]; |
||||
buffer[index++] = input; |
||||
if(index >= Length) |
||||
index = 0; |
||||
return output; |
||||
} |
||||
|
||||
void SetLength (int Length) |
||||
{ |
||||
if( Length >= maxLength ) |
||||
Length = maxLength; |
||||
if( Length < 0 ) |
||||
Length = 0; |
||||
|
||||
this->Length = Length; |
||||
} |
||||
|
||||
void Clear() |
||||
{ |
||||
std::memset(buffer, 0, sizeof(buffer)); |
||||
index = 0; |
||||
} |
||||
|
||||
int GetLength() const |
||||
{ |
||||
return Length; |
||||
} |
||||
}; |
||||
|
||||
template<typename T, int maxLength> |
||||
class StaticDelayLineFourTap |
||||
{ |
||||
private: |
||||
T buffer[maxLength]; |
||||
int index1, index2, index3, index4; |
||||
int Length; |
||||
T Feedback; |
||||
|
||||
public: |
||||
StaticDelayLineFourTap() |
||||
{ |
||||
SetLength ( maxLength - 1 ); |
||||
Clear(); |
||||
} |
||||
|
||||
//get ouput and iterate
|
||||
T operator()(T input) |
||||
{ |
||||
T output = buffer[index1]; |
||||
buffer[index1++] = input; |
||||
if(index1 >= Length) |
||||
index1 = 0; |
||||
if(++index2 >= Length) |
||||
index2 = 0; |
||||
if(++index3 >= Length) |
||||
index3 = 0; |
||||
if(++index4 >= Length) |
||||
index4 = 0; |
||||
return output; |
||||
} |
||||
|
||||
void SetIndex (int Index1, int Index2, int Index3, int Index4) |
||||
{ |
||||
index1 = Index1; |
||||
index2 = Index2; |
||||
index3 = Index3; |
||||
index4 = Index4; |
||||
} |
||||
|
||||
|
||||
T GetIndex (int Index) |
||||
{ |
||||
switch (Index) |
||||
{ |
||||
case 0: |
||||
return buffer[index1]; |
||||
break; |
||||
case 1: |
||||
return buffer[index2]; |
||||
break; |
||||
case 2: |
||||
return buffer[index3]; |
||||
break; |
||||
case 3: |
||||
return buffer[index4]; |
||||
break; |
||||
default: |
||||
return buffer[index1]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
void SetLength (int Length) |
||||
{ |
||||
if( Length >= maxLength ) |
||||
Length = maxLength; |
||||
if( Length < 0 ) |
||||
Length = 0; |
||||
|
||||
this->Length = Length; |
||||
} |
||||
|
||||
|
||||
void Clear() |
||||
{ |
||||
std::memset(buffer, 0, sizeof(buffer)); |
||||
index1 = index2 = index3 = index4 = 0; |
||||
} |
||||
|
||||
|
||||
int GetLength() const |
||||
{ |
||||
return Length; |
||||
} |
||||
}; |
||||
|
||||
template<typename T, int maxLength> |
||||
class StaticDelayLineEightTap |
||||
{ |
||||
private: |
||||
T buffer[maxLength]; |
||||
int index1, index2, index3, index4, index5, index6, index7, index8; |
||||
int Length; |
||||
T Feedback; |
||||
|
||||
public: |
||||
StaticDelayLineEightTap() |
||||
{ |
||||
SetLength ( maxLength - 1 ); |
||||
Clear(); |
||||
} |
||||
|
||||
//get ouput and iterate
|
||||
T operator()(T input) |
||||
{ |
||||
T output = buffer[index1]; |
||||
buffer[index1++] = input; |
||||
if(index1 >= Length) |
||||
index1 = 0; |
||||
if(++index2 >= Length) |
||||
index2 = 0; |
||||
if(++index3 >= Length) |
||||
index3 = 0; |
||||
if(++index4 >= Length) |
||||
index4 = 0; |
||||
if(++index5 >= Length) |
||||
index5 = 0; |
||||
if(++index6 >= Length) |
||||
index6 = 0; |
||||
if(++index7 >= Length) |
||||
index7 = 0; |
||||
if(++index8 >= Length) |
||||
index8 = 0; |
||||
return output; |
||||
|
||||
} |
||||
|
||||
void SetIndex (int Index1, int Index2, int Index3, int Index4, int Index5, int Index6, int Index7, int Index8) |
||||
{ |
||||
index1 = Index1; |
||||
index2 = Index2; |
||||
index3 = Index3; |
||||
index4 = Index4; |
||||
index5 = Index5; |
||||
index6 = Index6; |
||||
index7 = Index7; |
||||
index8 = Index8; |
||||
} |
||||
|
||||
|
||||
T GetIndex (int Index) |
||||
{ |
||||
switch (Index) |
||||
{ |
||||
case 0: |
||||
return buffer[index1]; |
||||
break; |
||||
case 1: |
||||
return buffer[index2]; |
||||
break; |
||||
case 2: |
||||
return buffer[index3]; |
||||
break; |
||||
case 3: |
||||
return buffer[index4]; |
||||
break; |
||||
case 4: |
||||
return buffer[index5]; |
||||
break; |
||||
case 5: |
||||
return buffer[index6]; |
||||
break; |
||||
case 6: |
||||
return buffer[index7]; |
||||
break; |
||||
case 7: |
||||
return buffer[index8]; |
||||
break; |
||||
default: |
||||
return buffer[index1]; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void SetLength (int Length) |
||||
{ |
||||
if( Length >= maxLength ) |
||||
Length = maxLength; |
||||
if( Length < 0 ) |
||||
Length = 0; |
||||
|
||||
this->Length = Length; |
||||
} |
||||
|
||||
|
||||
void Clear() |
||||
{ |
||||
std::memset(buffer, 0, sizeof(buffer)); |
||||
index1 = index2 = index3 = index4 = index5 = index6 = index7 = index8 = 0; |
||||
} |
||||
|
||||
|
||||
int GetLength() const |
||||
{ |
||||
return Length; |
||||
} |
||||
}; |
||||
|
||||
template<typename T, int OverSampleCount> |
||||
class StateVariable |
||||
{ |
||||
public: |
||||
|
||||
enum FilterType |
||||
{ |
||||
LOWPASS, |
||||
HIGHPASS, |
||||
BANDPASS, |
||||
NOTCH, |
||||
FilterTypeCount |
||||
}; |
||||
|
||||
private: |
||||
|
||||
T sampleRate; |
||||
T frequency; |
||||
T q; |
||||
T f; |
||||
|
||||
T low; |
||||
T high; |
||||
T band; |
||||
T notch; |
||||
|
||||
T *out; |
||||
|
||||
public: |
||||
StateVariable() |
||||
{ |
||||
SetSampleRate(44100.); |
||||
Frequency(1000.); |
||||
Resonance(0); |
||||
Type(LOWPASS); |
||||
Reset(); |
||||
} |
||||
|
||||
T operator()(T input) |
||||
{ |
||||
for(unsigned int i = 0; i < OverSampleCount; i++) |
||||
{ |
||||
low += f * band + 1e-25; |
||||
high = input - low - q * band; |
||||
band += f * high; |
||||
notch = low + high; |
||||
} |
||||
return *out; |
||||
} |
||||
|
||||
void Reset() |
||||
{ |
||||
low = high = band = notch = 0; |
||||
} |
||||
|
||||
void SetSampleRate(T sampleRate) |
||||
{ |
||||
this->sampleRate = sampleRate * OverSampleCount; |
||||
UpdateCoefficient(); |
||||
} |
||||
|
||||
void Frequency(T frequency) |
||||
{ |
||||
this->frequency = frequency; |
||||
UpdateCoefficient(); |
||||
} |
||||
|
||||
void Resonance(T resonance) |
||||
{ |
||||
this->q = 2 - 2 * resonance; |
||||
} |
||||
|
||||
void Type(int type) |
||||
{ |
||||
switch(type) |
||||
{ |
||||
case LOWPASS: |
||||
out = &low; |
||||
break; |
||||
|
||||
case HIGHPASS: |
||||
out = &high; |
||||
break; |
||||
|
||||
case BANDPASS: |
||||
out = &band; |
||||
break; |
||||
|
||||
case NOTCH: |
||||
out = ¬ch; |
||||
break; |
||||
|
||||
default: |
||||
out = &low; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
private: |
||||
void UpdateCoefficient() |
||||
{ |
||||
f = 2. * std::sin(PI * frequency / sampleRate); |
||||
} |
||||
}; |
||||
#endif |
Loading…
Reference in new issue