mirror of https://github.com/probonopd/MiniDexed
parent
116881b3a5
commit
e034e66f87
@ -0,0 +1,112 @@ |
||||
#include <circle/logger.h> |
||||
#include "effect_talreverb3.h" |
||||
|
||||
LOGMODULE ("fx talreverb3"); |
||||
|
||||
AudioEffectTalReverb3::AudioEffectTalReverb3(float32_t samplerate) : AudioEffect(samplerate) |
||||
{
|
||||
this->engine = new ReverbEngine(samplerate); |
||||
this->params = this->engine->param; |
||||
|
||||
this->setParameter(AudioEffectTalReverb3::Param::DRY, 50); |
||||
this->setParameter(AudioEffectTalReverb3::Param::WET, 23); |
||||
this->setParameter(AudioEffectTalReverb3::Param::DECAYTIME, 42); |
||||
this->setParameter(AudioEffectTalReverb3::Param::PREDELAY, 0); |
||||
this->setParameter(AudioEffectTalReverb3::Param::LOWSHELFGAIN, 89); |
||||
this->setParameter(AudioEffectTalReverb3::Param::HIGHSHELFGAIN, 33); |
||||
this->setParameter(AudioEffectTalReverb3::Param::STEREO, 100); |
||||
this->setParameter(AudioEffectTalReverb3::Param::REALSTEREOMODE, 100); |
||||
this->setParameter(AudioEffectTalReverb3::Param::POWER, 100); |
||||
} |
||||
|
||||
AudioEffectTalReverb3::~AudioEffectTalReverb3() |
||||
{ |
||||
delete this->engine; |
||||
} |
||||
|
||||
void AudioEffectTalReverb3::setParameter(unsigned param, unsigned value) |
||||
{ |
||||
|
||||
this->params[param] = value; |
||||
switch (param) |
||||
{ |
||||
case AudioEffectTalReverb3::Param::BYPASS: |
||||
this->setBypass(value == 1); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::WET: |
||||
this->engine->setWet((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::DRY: |
||||
this->engine->setDry((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::DECAYTIME: |
||||
this->engine->setDecayTime((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::PREDELAY: |
||||
this->engine->setPreDelay((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::LOWSHELFGAIN: |
||||
this->engine->setLowShelfGain((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::HIGHSHELFGAIN: |
||||
this->engine->setHighShelfGain((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::STEREO: |
||||
this->engine->setStereoWidth((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::REALSTEREOMODE: |
||||
this->engine->setStereoMode((float) value / 100.0f); |
||||
break; |
||||
case AudioEffectTalReverb3::Param::POWER: |
||||
this->engine->setPower((float) value / 100.0f); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
unsigned AudioEffectTalReverb3::getParameter(unsigned param) |
||||
{ |
||||
switch (param) |
||||
{ |
||||
case AudioEffectTalReverb3::Param::BYPASS: |
||||
return this->getBypass() ? 1 : 0; |
||||
case AudioEffectTalReverb3::Param::WET: |
||||
case AudioEffectTalReverb3::Param::DRY: |
||||
case AudioEffectTalReverb3::Param::DECAYTIME: |
||||
case AudioEffectTalReverb3::Param::PREDELAY: |
||||
case AudioEffectTalReverb3::Param::LOWSHELFGAIN: |
||||
case AudioEffectTalReverb3::Param::HIGHSHELFGAIN: |
||||
case AudioEffectTalReverb3::Param::STEREO: |
||||
case AudioEffectTalReverb3::Param::REALSTEREOMODE: |
||||
case AudioEffectTalReverb3::Param::POWER: |
||||
return params[param]; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
void AudioEffectTalReverb3::doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len) |
||||
{ |
||||
int numberOfChannels = 2; |
||||
if (inblockL == inblockR) { |
||||
numberOfChannels = 1; |
||||
} |
||||
|
||||
for (size_t i = 0; i < len; i++) |
||||
{ |
||||
if (numberOfChannels == 2) |
||||
{ |
||||
outblockL[i] = inblockL[i]; |
||||
outblockR[i] = inblockR[i]; |
||||
} |
||||
else |
||||
{ |
||||
outblockL[i] = inblockL[i]; |
||||
outblockR[i] = inblockL[i]; |
||||
} |
||||
|
||||
engine->process(&outblockL[i], &outblockR[i]); |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
#ifndef _EFFECT_TALREVERB3_H |
||||
#define _EFFECT_TALREVERB3_H |
||||
|
||||
#include "effect_base.h" |
||||
#include "tal-reverb-3/ReverbEngine.h" |
||||
|
||||
class AudioEffectTalReverb3 : public AudioEffect |
||||
{ |
||||
public: |
||||
static const unsigned MAX_DELAY_TIME = 1; |
||||
|
||||
enum Param |
||||
{ |
||||
BYPASS, |
||||
DRY, |
||||
WET, |
||||
DECAYTIME, |
||||
PREDELAY, |
||||
LOWSHELFGAIN, |
||||
HIGHSHELFGAIN, |
||||
STEREO, |
||||
REALSTEREOMODE, |
||||
POWER, |
||||
UNKNOWN |
||||
}; |
||||
|
||||
AudioEffectTalReverb3(float32_t samplerate); |
||||
virtual ~AudioEffectTalReverb3(); |
||||
|
||||
virtual unsigned getId() |
||||
{ |
||||
return EFFECT_TALREVERB3; |
||||
} |
||||
|
||||
virtual void setParameter(unsigned param, unsigned value); |
||||
virtual unsigned getParameter(unsigned param); |
||||
protected: |
||||
virtual size_t getParametersSize() |
||||
{ |
||||
return sizeof(AudioEffectTalReverb3::Param); |
||||
} |
||||
virtual void doProcess(const float32_t* inblockL, const float32_t* inblockR, float32_t* outblockL, float32_t* outblockR, uint16_t len); |
||||
private: |
||||
float *params; |
||||
ReverbEngine *engine; |
||||
}; |
||||
|
||||
#endif // _EFFECT_TALREVERB3_H
|
@ -0,0 +1,127 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__AllPassFilter_h) |
||||
#define __AllPassFilter_h |
||||
|
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
|
||||
class AllPassFilter |
||||
{ |
||||
private: |
||||
float delay, gain; |
||||
float* buffer; |
||||
int bufferLength, writePtr, readPtr1, readPtr2; |
||||
float z1; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
// delay times in milliseconds
|
||||
AllPassFilter(float delayTime, float feedbackGain, long samplingRate) |
||||
{ |
||||
//OutputDebugString("start init allPass");
|
||||
gain = feedbackGain; |
||||
delay = delayTime; |
||||
|
||||
bufferLength = (int)(delay * samplingRate / 1000.0f); |
||||
bufferLength = audioUtils.getNextNearPrime(bufferLength); |
||||
buffer = new float[bufferLength]; |
||||
|
||||
//zero out the buffer (create silence)
|
||||
for (int i = 0; i < bufferLength; i++) |
||||
buffer[i] = 0.0f; |
||||
|
||||
writePtr = readPtr1 = readPtr2 = 0; |
||||
z1 = 0.0f; |
||||
//OutputDebugString("end init allPass");
|
||||
} |
||||
|
||||
~AllPassFilter() |
||||
{ |
||||
delete buffer; |
||||
} |
||||
|
||||
// all values [0..1]
|
||||
inline float processInterpolated(float input, float delayLength, float diffuse, bool negative) |
||||
{ |
||||
// dynamic delay length
|
||||
float offset = (bufferLength - 2.0f) * delayLength + 1.0f; |
||||
readPtr1 = writePtr - (int)floorf(offset); |
||||
|
||||
if (readPtr1 < 0) |
||||
readPtr1 += bufferLength; |
||||
|
||||
readPtr2 = readPtr1 - 1; |
||||
if (readPtr2 < 0) |
||||
readPtr2 += bufferLength; |
||||
|
||||
// interpolate, see paper: http://www.stanford.edu/~dattorro/EffectDesignPart2.pdf
|
||||
float frac = offset - (int)floorf(offset); |
||||
float temp = buffer[readPtr2] + buffer[readPtr1] * (1-frac) - (1-frac) * z1; |
||||
z1 = temp; |
||||
|
||||
float output; |
||||
if (!negative) |
||||
{ |
||||
buffer[writePtr] = diffuse * gain * temp + input; |
||||
output = temp - diffuse * gain * buffer[writePtr]; |
||||
} |
||||
else |
||||
{ |
||||
buffer[writePtr] = diffuse * gain * temp - input; |
||||
output = temp + diffuse * gain * buffer[writePtr]; |
||||
} |
||||
|
||||
if (++writePtr >= bufferLength) |
||||
writePtr = 0; |
||||
|
||||
return output; |
||||
} |
||||
|
||||
inline float process(float input, float diffuse) |
||||
{ |
||||
float temp = buffer[readPtr1]; |
||||
buffer[readPtr1] = diffuse * gain * temp + input; |
||||
float output = temp - diffuse * gain * buffer[readPtr1]; |
||||
|
||||
if (++readPtr1 >= bufferLength) |
||||
readPtr1 = 0; |
||||
|
||||
return output; |
||||
} |
||||
|
||||
inline float process(float input) |
||||
{ |
||||
float temp = buffer[readPtr1]; |
||||
buffer[readPtr1] = gain * temp + input; |
||||
float output = temp - gain * buffer[readPtr1]; |
||||
|
||||
if (++readPtr1 >= bufferLength) |
||||
readPtr1 = 0; |
||||
|
||||
return output; |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,155 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Dub-III by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__AudioUtils_h) |
||||
#define __AudioUtils_h |
||||
|
||||
#include "math.h" |
||||
|
||||
class AudioUtils
|
||||
{ |
||||
private: |
||||
|
||||
public: |
||||
AudioUtils()
|
||||
{ |
||||
} |
||||
|
||||
~AudioUtils() |
||||
{ |
||||
} |
||||
|
||||
float getLogScaledValueInDecibel(float inputValue, float maxValue) |
||||
{ |
||||
float logScaled = getLogScaledVolume(inputValue, maxValue); |
||||
return getValueInDecibel(logScaled); |
||||
} |
||||
|
||||
float getLogScaledValueInDecibelFilter(float inputValue, float maxValue) |
||||
{ |
||||
float logScaled = getLogScaledVolume(inputValue, maxValue); |
||||
return getValueInDecibelFilter(logScaled); |
||||
} |
||||
|
||||
// max value unscalled
|
||||
float getLogScaledVolume(float inputValue, float maxValue) |
||||
{ |
||||
return (expf(inputValue * maxValue * logf(20.0f)) - 1.0f) / 19.0f; |
||||
}
|
||||
|
||||
// max value unscalled
|
||||
float getLogScaledValue(float inputValue) |
||||
{ |
||||
// have to return a value between 0..1
|
||||
return (expf(inputValue * logf(20.0f)) - 1.0f) / 19.0f; |
||||
} |
||||
|
||||
float getLogScaledValue(float inputValue, float expValue) |
||||
{ |
||||
// have to return a value between 0..1
|
||||
return (expf(inputValue * logf(expValue)) - 1.0f) / (expValue - 1.0f); |
||||
} |
||||
|
||||
float getLogScaledFrequency(float inputValue) |
||||
{ |
||||
return 100.0f + getLogScaledValue(inputValue) * 9900.0f; |
||||
} |
||||
|
||||
float getLogScaledValueInverted(float inputValue) |
||||
{ |
||||
// have to return a value between 0..1
|
||||
inputValue = 1.0f - inputValue; |
||||
inputValue = (expf(inputValue * logf(20.0f)) - 1.0f) / 19.0f; |
||||
return 1.0f - inputValue; |
||||
} |
||||
|
||||
float getLogScaledValueInverted(float inputValue, int exponent) |
||||
{ |
||||
// have to return a value between 0..1
|
||||
inputValue = 1.0f - inputValue; |
||||
inputValue = (expf(inputValue * logf((float)exponent)) - 1.0f) / (exponent - 1.0f); |
||||
return 1.0f - inputValue; |
||||
} |
||||
|
||||
// input value >= 0
|
||||
float getValueInDecibel(float inputValue) |
||||
{ |
||||
if (inputValue <= 0) |
||||
{ |
||||
return -96.0f; |
||||
} |
||||
else |
||||
{ |
||||
// 1.0 --> 0dB
|
||||
return 20.0f * log10f(inputValue / 1.0f); |
||||
} |
||||
} |
||||
|
||||
float getValueInDecibelFilter(float inputValue) |
||||
{ |
||||
if (inputValue <= 0) |
||||
{ |
||||
return -18.0f; |
||||
} |
||||
else |
||||
{ |
||||
// 1.0 --> 0dB
|
||||
return 5.0f * log10f(inputValue / 1.0f); |
||||
} |
||||
} |
||||
|
||||
inline float tanhApp(float x)
|
||||
{ |
||||
// Original
|
||||
//return tanh(x);
|
||||
|
||||
// Approx
|
||||
x*= 2.0f; |
||||
float a= fabs(x); |
||||
float b= 6.0f + a*(3.0f + a); // 6, 3
|
||||
return (x * b)/(a * b + 12.0f); |
||||
} |
||||
|
||||
inline int getNextNearPrime(int value) |
||||
{ |
||||
while (!isPrime(value)) value++; |
||||
return value; |
||||
} |
||||
|
||||
inline bool isPrime(int value) |
||||
{ |
||||
bool answer = true; |
||||
if (value == 0) value = 1; |
||||
for (int i = 2; i <= sqrtf((float)value) ; i++)
|
||||
{ |
||||
if (value % i == 0) |
||||
{ |
||||
answer = false; |
||||
break; |
||||
} |
||||
} |
||||
return answer; |
||||
} |
||||
}; |
||||
#endif |
||||
|
@ -0,0 +1,123 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__CombFilter_h) |
||||
#define __CombFilter_h |
||||
|
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
|
||||
class CombFilter |
||||
{ |
||||
private: |
||||
float sampleRateFactor; |
||||
|
||||
float gain, minDamp; |
||||
float* buffer; |
||||
int readPtr1, readPtr2, writePtr; |
||||
float z1; |
||||
int bufferLengthDelay; |
||||
float filterStore; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
// delay times in milliseconds
|
||||
CombFilter(float delayTime, float minDamp, long sampleRate) |
||||
{ |
||||
bufferLengthDelay = (int)(delayTime * sampleRate / 1000); |
||||
bufferLengthDelay = audioUtils.getNextNearPrime(bufferLengthDelay); |
||||
buffer = new float[bufferLengthDelay]; |
||||
|
||||
//zero out the buffer (silence)
|
||||
for (int i = 0; i < bufferLengthDelay; i++) |
||||
buffer[i] = 0.0f; |
||||
|
||||
writePtr = 0; |
||||
|
||||
//set read pointer to start of buffer
|
||||
readPtr1 = 0; |
||||
z1 = filterStore = 0.0f; |
||||
this->minDamp = minDamp; |
||||
|
||||
this->sampleRateFactor = 44100.0f / sampleRate; |
||||
if (this->sampleRateFactor > 1.0f) |
||||
{ |
||||
this->sampleRateFactor = 1.0f; |
||||
} |
||||
} |
||||
|
||||
~CombFilter() |
||||
{ |
||||
delete buffer; |
||||
} |
||||
|
||||
// delayIntensity [0..1]
|
||||
inline float processInterpolated(float input, float damp, float feedback, float delay) |
||||
{ |
||||
damp *= this->sampleRateFactor; |
||||
|
||||
float offset = (bufferLengthDelay - 2) * delay + 1.0f; |
||||
readPtr1 = writePtr - (int)floorf(offset); |
||||
|
||||
if (readPtr1 < 0)
|
||||
readPtr1 += bufferLengthDelay; |
||||
|
||||
readPtr2 = readPtr1 - 1; |
||||
if (readPtr2 < 0)
|
||||
readPtr2 += bufferLengthDelay; |
||||
|
||||
// interpolate, see paper: http://www.stanford.edu/~dattorro/EffectDesignPart2.pdf
|
||||
float frac = offset - (int)floorf(offset); |
||||
float output = buffer[readPtr2] + buffer[readPtr1] * (1-frac) - (1-frac) * z1; |
||||
z1 = output; |
||||
|
||||
damp = minDamp * damp; |
||||
filterStore = output * (1.0f - damp) + filterStore * damp; |
||||
buffer[writePtr] = input + (filterStore * feedback); |
||||
|
||||
if (++writePtr >= bufferLengthDelay)
|
||||
writePtr = 0; |
||||
return output; |
||||
} |
||||
|
||||
inline float process(float input, float damp, float feedback, float delay) |
||||
{ |
||||
damp *= this->sampleRateFactor; |
||||
|
||||
float offset = (bufferLengthDelay - 2) * delay + 1.0f; |
||||
readPtr1 = writePtr - (int)floorf(offset); |
||||
|
||||
if (readPtr1 < 0)
|
||||
readPtr1 += bufferLengthDelay; |
||||
|
||||
float output = buffer[readPtr1]; |
||||
filterStore = output * (1.0f - damp) + filterStore * damp; |
||||
buffer[writePtr] = input + (filterStore * feedback); |
||||
|
||||
if (++writePtr >= bufferLengthDelay) |
||||
writePtr = 0; |
||||
return output; |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,88 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__Filter_h) |
||||
#define __Filter_h |
||||
|
||||
#include "math.h" |
||||
|
||||
class Filter |
||||
{ |
||||
private: |
||||
float f, k, p, scale, r, x; |
||||
float y1, y2, y3, y4, oldx, oldy1, oldy2, oldy3; |
||||
float fCutoff, fActualCutoff; |
||||
float Pi; |
||||
|
||||
float sampleRateFactor; |
||||
|
||||
public: |
||||
|
||||
Filter(float sampleRate) |
||||
{ |
||||
Pi = 3.141592653f; |
||||
y1 = y2 = y3 = y4 = oldx = oldy1 = oldy2 = oldy3 = 0.0f; |
||||
|
||||
if (sampleRate <= 0.0f) sampleRate = 44100.0f; |
||||
|
||||
sampleRateFactor= 44100.0f / sampleRate; |
||||
if (sampleRateFactor > 1.0f) |
||||
sampleRateFactor = 1.0f; |
||||
|
||||
fActualCutoff = -1.0f; |
||||
} |
||||
|
||||
inline float process(float input, float fCutoff, float fRes, bool highPass) |
||||
{ |
||||
if (fCutoff != fActualCutoff) |
||||
{ |
||||
fActualCutoff = fCutoff; |
||||
fCutoff *= sampleRateFactor; |
||||
updateValues(fCutoff * fCutoff); |
||||
} |
||||
x = input;
|
||||
|
||||
// Four cascaded onepole filters (bilinear transform)
|
||||
y1 = (x + oldx) * p - k * y1; |
||||
y2 = (y1 + oldy1) * p - k * y2; |
||||
|
||||
// Save values
|
||||
oldx = x; |
||||
oldy1 = y1; |
||||
if (highPass) input = input - y2; |
||||
else input = y2; |
||||
return input; |
||||
} |
||||
|
||||
void updateValues(float fCutoff) |
||||
{ |
||||
// Filter section MOOG VCF
|
||||
// CSound source code, Stilson/Smith CCRMA paper.
|
||||
f = fCutoff; // [0 - 1]
|
||||
k = 3.6f * f - 1.6f * f * f - 1.0f; // (Empirical tunning) /// !!! original (convex)
|
||||
|
||||
p = (k + 1.0f) * 0.5f; // scale [0, 1]
|
||||
scale = expf((1.0f - p) * 1.386249f); // original
|
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,126 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__HighShelf_h) |
||||
#define __HighShelf_h |
||||
|
||||
#include "math.h" |
||||
|
||||
class HighShelf
|
||||
{ |
||||
public: |
||||
int filterDecibel; |
||||
|
||||
float sampleRate; |
||||
|
||||
float a0, a1, a2; |
||||
float b0, b1, b2; |
||||
|
||||
float x0, x1, x2; |
||||
float y1, y2; |
||||
|
||||
float outSample; |
||||
|
||||
float a, w0, q, s, alpha; |
||||
float cosValue, sqrtValue; |
||||
|
||||
float dBgain, freq; |
||||
|
||||
|
||||
HighShelf(float sampleRate, int filterDecibel)
|
||||
{ |
||||
this->sampleRate = sampleRate; |
||||
this->filterDecibel = filterDecibel; |
||||
|
||||
a0 = a1 = a2 = 0.0f; |
||||
b0 = b1 = b2 = 0.0f; |
||||
|
||||
x0 = x1 = x2 = 0.0f; |
||||
y1 = y2 = 0.0f; |
||||
|
||||
q = dBgain = freq = 0.0f; |
||||
|
||||
s = 2.0f; |
||||
} |
||||
|
||||
// gain [0..1], q[0..1], freq[0..44100]
|
||||
inline void tick(float *inSample, float freq, float q, float gain)
|
||||
{ |
||||
gain = filterDecibel - (1.0f - gain) * filterDecibel * 2.0f; |
||||
calcCoefficients(freq, q, gain); |
||||
|
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
updateHistory(*inSample, outSample); |
||||
*inSample = outSample; |
||||
} |
||||
|
||||
inline void calcCoefficients(float freq, float q, float dBgain) |
||||
{ |
||||
if (this->q != q || this->dBgain != dBgain || this->freq != freq) |
||||
{ |
||||
this->dBgain = dBgain; |
||||
this->q = q; |
||||
this->freq = freq; |
||||
w0 = 2.0f * 3.141592653589793f * freq / sampleRate; |
||||
a = sqrtf(pow(10, dBgain/20.0f)); |
||||
alpha = sinf(w0)/(2.0f*q); |
||||
q = 1.0f / sqrt((a + 1.0f/a)*(1.0f/s - 1.0f) + 2.0f); |
||||
|
||||
cosValue = cosf(w0); |
||||
sqrtValue = sqrtf(a); |
||||
} |
||||
|
||||
b0 = a * ((a + 1.0f) + (a - 1.0f) * cosValue + 2.0f * sqrtValue * alpha ); |
||||
b1 = -2.0f * a * ((a - 1.0f) + (a + 1.0f) * cosValue ); |
||||
b2 = a * ((a + 1.0f) + (a - 1.0f) * cosValue - 2.0f * sqrtValue * alpha ); |
||||
a0 = (a + 1.0f) - (a - 1.0f) * cosValue + 2.0f * sqrtValue * alpha; |
||||
a1 = 2.0f * ((a - 1.0f) - (a + 1.0f) * cosValue ); |
||||
a2 = (a + 1.0f) - (a - 1.0f) * cosValue - 2.0f * sqrtValue * alpha; |
||||
|
||||
a0 = 1.0f/a0; |
||||
|
||||
b0 *= a0; |
||||
b1 *= a0; |
||||
b2 *= a0; |
||||
a1 *= a0; |
||||
a2 *= a0; |
||||
} |
||||
|
||||
inline void updateHistory(float inSample, float outSample) |
||||
{ |
||||
x0 = saturate(x1, -0.05f); |
||||
x1 = saturate(x2, 0.04f); |
||||
x2 = inSample; |
||||
|
||||
y2 = y1; |
||||
y1 = outSample; |
||||
} |
||||
|
||||
inline float saturate(float x, float variation) |
||||
{ |
||||
return x - 0.002f * (x + variation) * x * x; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,127 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__LowShelf_h) |
||||
#define __LowShelf_h |
||||
|
||||
#include "math.h" |
||||
|
||||
class LowShelf
|
||||
{ |
||||
public: |
||||
int filterDecibel; |
||||
|
||||
float sampleRate; |
||||
|
||||
float a0, a1, a2; |
||||
float b0, b1, b2; |
||||
|
||||
float x0, x1, x2; |
||||
float y1, y2; |
||||
|
||||
float outSample; |
||||
|
||||
float a, w0, q, s, alpha; |
||||
float cosValue, sqrtValue; |
||||
|
||||
float dBgain, freq; |
||||
|
||||
float random; |
||||
|
||||
LowShelf(float sampleRate, int filterDecibel)
|
||||
{ |
||||
this->sampleRate = sampleRate; |
||||
this->filterDecibel = filterDecibel; |
||||
|
||||
a0 = a1 = a2 = 0.0f; |
||||
b0 = b1 = b2 = 0.0f; |
||||
|
||||
x0 = x1 = x2 = 0.0f; |
||||
y1 = y2 = 0.0f; |
||||
|
||||
q = dBgain = freq = 0.0f; |
||||
|
||||
s = 1.0f; |
||||
} |
||||
|
||||
// gain [0..1], q[0..1], freq[0..44100]
|
||||
inline void tick(float *inSample, float freq, float q, float gain)
|
||||
{ |
||||
gain = filterDecibel - (1.0f - gain) * filterDecibel * 2.0f; |
||||
calcCoefficients(freq, q, gain); |
||||
|
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
updateHistory(*inSample, outSample); |
||||
*inSample = outSample; |
||||
} |
||||
|
||||
inline void calcCoefficients(float freq, float q, float dBgain) |
||||
{ |
||||
if (this->q != q || this->dBgain != dBgain || this->freq != freq) |
||||
{ |
||||
this->dBgain = dBgain; |
||||
this->q = q; |
||||
this->freq = freq; |
||||
w0 = 2.0f * 3.141592653589793f * freq / sampleRate; |
||||
|
||||
a = sqrtf(pow(10, dBgain/20.0f)); |
||||
alpha = sinf(w0)/(2.0f*q); |
||||
q = 1.0f / sqrt((a + 1.0f/a)*(1.0f/s - 1.0f) + 2.0f); |
||||
|
||||
cosValue = cosf(w0); |
||||
sqrtValue = sqrtf(a); |
||||
}
|
||||
b0 = a * ((a + 1.0f) - (a - 1.0f) * cosValue + 2.0f * sqrtValue * alpha ); |
||||
b1 = 2.0f * a * ((a - 1.0f) - (a + 1.0f) * cosValue ); |
||||
b2 = a * ((a + 1.0f) - (a - 1.0f) * cosValue - 2.0f * sqrtValue * alpha ); |
||||
a0 = (a + 1.0f) + (a - 1.0f) * cosValue + 2.0f * sqrtValue * alpha; |
||||
a1 = - 2.0f * ((a - 1.0f) + (a + 1.0f) * cosValue ); |
||||
a2 = (a + 1.0f) + (a - 1.0f) * cosValue - 2.0f * sqrtValue * alpha; |
||||
|
||||
a0 = 1.0f/a0; |
||||
|
||||
b0 *= a0; |
||||
b1 *= a0; |
||||
b2 *= a0; |
||||
a1 *= a0; |
||||
a2 *= a0; |
||||
} |
||||
|
||||
inline void updateHistory(float inSample, float outSample) |
||||
{ |
||||
x0 = saturate(x1, -0.08f); |
||||
x1 = saturate(x2, 0.05f); |
||||
x2 = saturate(inSample, 0.01f); |
||||
|
||||
y2 = y1; |
||||
y1 = outSample; |
||||
} |
||||
|
||||
inline float saturate(float x, float variation) |
||||
{ |
||||
return x - 0.002f * (x + variation) * x * x; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,110 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__NoiseGenerator_h) |
||||
#define __NoiseGenerator_h |
||||
|
||||
#include <cstdlib> |
||||
|
||||
class NoiseGenerator
|
||||
{ |
||||
public: |
||||
float sampleRate; |
||||
|
||||
int randomSeed; |
||||
float actualValue; |
||||
float deltaValue; |
||||
|
||||
float actualValueFiltered; |
||||
float filterFactor; |
||||
float filterFactorInversePlusOne; |
||||
|
||||
float periodRange; |
||||
float periodOffset; |
||||
|
||||
float noiseFastModFilterValue; |
||||
|
||||
NoiseGenerator(float sampleRate, float randomSeed)
|
||||
{ |
||||
this->sampleRate = sampleRate; |
||||
this->randomSeed = (int)randomSeed; |
||||
|
||||
this->filterFactor = 44100.0f * 2800.0f / sampleRate; |
||||
this->filterFactorInversePlusOne = 1.0f / (filterFactor + 1.0f); |
||||
|
||||
this->periodRange = 44100.0f * 25000.0f / sampleRate; |
||||
this->periodOffset = 44100.0f * 1000.0f / sampleRate; |
||||
|
||||
this->noiseFastModFilterValue = 44100.0f * 10.0f / sampleRate; |
||||
//this->noiseFastModFilterValue = 10.0f;
|
||||
|
||||
this->deltaValue = 0.0f; |
||||
this->actualValue = 0.0f; |
||||
this->actualValueFiltered = 0.0f; |
||||
|
||||
this->getNextRandomPeriod(1.0f); |
||||
|
||||
} |
||||
|
||||
// returns a random value [0..1]
|
||||
inline float tickNoise()
|
||||
{ |
||||
// return ((float)(((randSeed = randSeed * 214013L + 2531011L) >> 16) & 0x7fff)/RAND_MAX);
|
||||
|
||||
this->randomSeed *= 16807; |
||||
return (float)(randomSeed & 0x7FFFFFFF) * 4.6566129e-010f; |
||||
//return (float)randSeed * 4.6566129e-010f;
|
||||
} |
||||
|
||||
// returns a lp filtered random value [0..1]
|
||||
inline float tickFilteredNoise()
|
||||
{ |
||||
if (actualValue >= 1.0f) |
||||
{ |
||||
getNextRandomPeriod(-1.0f); |
||||
} |
||||
if (actualValue <= 0.0f) |
||||
{ |
||||
getNextRandomPeriod(1.0f); |
||||
} |
||||
actualValue += deltaValue; |
||||
|
||||
// Exponential averager
|
||||
actualValueFiltered = (actualValueFiltered * filterFactor + actualValue) * filterFactorInversePlusOne; |
||||
return actualValueFiltered; |
||||
} |
||||
|
||||
inline void getNextRandomPeriod(float sign) |
||||
{ |
||||
int randomPeriod = (int)(tickNoise() * this->periodRange + this->periodOffset); |
||||
deltaValue = 1.0f / (float)randomPeriod; |
||||
deltaValue *= sign; |
||||
} |
||||
|
||||
inline float tickFilteredNoiseFast()
|
||||
{ |
||||
actualValueFiltered = (actualValueFiltered * this->noiseFastModFilterValue + tickNoise()) / (this->noiseFastModFilterValue + 1.0f); |
||||
return actualValueFiltered; |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,52 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__ParamChangeUtil_h) |
||||
#define __ParamChangeUtil_h |
||||
|
||||
#include "math.h" |
||||
|
||||
// Low pass filter for gentle parameter changes
|
||||
class ParamChangeUtil |
||||
{ |
||||
private: |
||||
float currentValue; |
||||
float paramWeight; |
||||
float paramWeigthInverse; |
||||
|
||||
public: |
||||
// param weight should be bigger than 1
|
||||
ParamChangeUtil(float sampleRate, float paramWeight) |
||||
{ |
||||
currentValue = 0; |
||||
this->paramWeight = paramWeight * sampleRate / 44100.0f; |
||||
paramWeigthInverse = 1.0f / (this->paramWeight + 1.0f); |
||||
} |
||||
|
||||
inline float tick(float input) |
||||
{ |
||||
currentValue = (paramWeight * currentValue + input) * paramWeigthInverse; |
||||
return currentValue; |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,72 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#ifndef Params_H |
||||
#define Params_H |
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
Kunz Patrick |
||||
|
||||
Parameter table |
||||
|
||||
-----------------------------------------------------------------------------*/ |
||||
|
||||
enum SYNTHPARAMETERS |
||||
{ |
||||
// Controllable values [0.0..1.0
|
||||
UNUSED= 0, |
||||
DRY, |
||||
WET, |
||||
|
||||
DECAYTIME, |
||||
PREDELAY, |
||||
|
||||
LOWSHELFGAIN, |
||||
HIGHSHELFGAIN, |
||||
|
||||
STEREO, |
||||
REALSTEREOMODE, |
||||
|
||||
POWER, |
||||
|
||||
// Number of controllable synth paramenters
|
||||
NUMPARAM, |
||||
NUMPROGRAMS = 10, |
||||
}; |
||||
|
||||
class Params |
||||
{ |
||||
public: |
||||
float *parameters; |
||||
|
||||
Params() { |
||||
parameters= new float[NUMPARAM]; |
||||
|
||||
// Zero program values
|
||||
for(int j=0; j<NUMPARAM; j++) { |
||||
parameters[j]= 0.0f; |
||||
} |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,104 @@ |
||||
#if !defined(__PeakEq_h) |
||||
#define __PeakEq_h |
||||
|
||||
#include <stdio.h> |
||||
#include "math.h" |
||||
|
||||
class PeakEq
|
||||
{ |
||||
public: |
||||
int filterDecibel; |
||||
|
||||
float sampleRate; |
||||
|
||||
float a0, a1, a2; |
||||
float b0, b1, b2; |
||||
|
||||
float x0, x1, x2; |
||||
float y1, y2; |
||||
|
||||
float outSample; |
||||
|
||||
float a, w0, q, s, alpha; |
||||
float cosValue, sqrtValue; |
||||
|
||||
float dBgain, freq; |
||||
|
||||
|
||||
PeakEq(float sampleRate, int filterDecibel)
|
||||
{ |
||||
this->sampleRate = sampleRate; |
||||
this->filterDecibel = filterDecibel; |
||||
|
||||
a0 = a1 = a2 = 0.0f; |
||||
b0 = b1 = b2 = 0.0f; |
||||
|
||||
x0 = x1 = x2 = 0.0f; |
||||
y1 = y2 = 0.0f; |
||||
|
||||
q = dBgain = freq = 0.0f; |
||||
|
||||
s = 2.0f; |
||||
} |
||||
|
||||
// gain [0..1], q[0..1], freq[0..44100]
|
||||
inline void tick(float *inSample, float freq, float q, float gain)
|
||||
{ |
||||
gain = filterDecibel - (1.0f - gain) * filterDecibel * 2.0f; |
||||
calcCoefficients(freq, q, gain); |
||||
|
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
outSample = b0*x0 + b1*x1 + b2*x2 - a1*y1 - a2*y2; |
||||
updateHistory(*inSample, outSample); |
||||
*inSample = outSample; |
||||
} |
||||
|
||||
inline void calcCoefficients(float freq, float q, float dBgain) |
||||
{ |
||||
if (this->q != q || this->dBgain != dBgain || this->freq != freq) |
||||
{ |
||||
this->dBgain = dBgain; |
||||
this->q = q; |
||||
this->freq = freq; |
||||
w0 = 2.0f * 3.141592653589793f * freq / sampleRate; |
||||
a = sqrtf(pow(10, dBgain/20.0f)); |
||||
alpha = sinf(w0)*sinhf( logf(2.0f)/2.0f * q * w0/sinf(w0)); |
||||
// q = 1.0f / sqrt((a + 1.0f/a)*(1.0f/s - 1.0f) + 2.0f);
|
||||
|
||||
cosValue = cosf(w0); |
||||
sqrtValue = sqrtf(a); |
||||
} |
||||
|
||||
b0 = 1.0f + alpha * a; |
||||
b1 = -2.0f * cosValue; |
||||
b2 = 1.0f - alpha * a; |
||||
a0 = 1.0f + alpha / a; |
||||
a1 = -2.0f * cosValue; |
||||
a2 = 1.0f - alpha / a; |
||||
|
||||
a0 = 1.0f/a0; |
||||
|
||||
b0 *= a0; |
||||
b1 *= a0; |
||||
b2 *= a0; |
||||
a1 *= a0; |
||||
a2 *= a0; |
||||
} |
||||
|
||||
inline void updateHistory(float inSample, float outSample) |
||||
{ |
||||
x0 = saturate(x1, -0.05f); |
||||
x1 = saturate(x2, 0.04f); |
||||
x2 = inSample; |
||||
|
||||
y2 = y1; |
||||
y1 = outSample; |
||||
} |
||||
|
||||
inline float saturate(float x, float variation) |
||||
{ |
||||
return x - 0.002f * (x + variation) * x * x; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,303 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
|
||||
#if !defined(__Reverb_h) |
||||
#define __Reverb_h |
||||
|
||||
#include "AllPassFilter.h" |
||||
#include "CombFilter.h" |
||||
#include "NoiseGenerator.h" |
||||
#include "Filter.h" |
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
#include "TalEq.h" |
||||
|
||||
class Reverb |
||||
{ |
||||
private: |
||||
static const int DELAY_LINES_COMB = 4; |
||||
static const int DELAY_LINES_ALLPASS = 5; |
||||
|
||||
static const int MAX_PRE_DELAY_MS = 1000; |
||||
float* reflectionGains; |
||||
float* reflectionDelays; |
||||
|
||||
CombFilter *combFiltersPreDelayL; |
||||
CombFilter *combFiltersPreDelayR; |
||||
|
||||
CombFilter **combFiltersL; |
||||
CombFilter **combFiltersR; |
||||
NoiseGenerator **noiseGeneratorAllPassL; |
||||
NoiseGenerator **noiseGeneratorAllPassR; |
||||
NoiseGenerator **noiseGeneratorDelayL; |
||||
NoiseGenerator **noiseGeneratorDelayR; |
||||
NoiseGenerator **diffusionL; |
||||
NoiseGenerator **diffusionR; |
||||
|
||||
AllPassFilter **allPassFiltersL; |
||||
AllPassFilter **allPassFiltersR; |
||||
|
||||
AllPassFilter *preAllPassFilterL; |
||||
AllPassFilter *preAllPassFilterR; |
||||
|
||||
AllPassFilter *postAllPassFilterL; |
||||
AllPassFilter *postAllPassFilterR; |
||||
|
||||
TalEq* talEqL; |
||||
TalEq* talEqR; |
||||
|
||||
float feedbackValueL; |
||||
float feedbackValueR; |
||||
|
||||
float decayTime; |
||||
float preDelayTime; |
||||
bool stereoMode; |
||||
float modulationIntensity; |
||||
|
||||
float outL; |
||||
float outR; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
Reverb(int sampleRate) |
||||
{ |
||||
createDelaysAndCoefficients(DELAY_LINES_COMB + DELAY_LINES_ALLPASS, 82.0f); |
||||
|
||||
combFiltersPreDelayL = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
combFiltersPreDelayR = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
|
||||
combFiltersL = new CombFilter *[DELAY_LINES_COMB]; |
||||
combFiltersR = new CombFilter *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
|
||||
float stereoSpreadValue = 0.008f; |
||||
float stereoSpreadSign = 1.0f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{ |
||||
float stereoSpreadFactor = 1.0f + stereoSpreadValue; |
||||
if (stereoSpreadSign > 0.0f) |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
} |
||||
else |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
} |
||||
stereoSpreadSign *= -1.0f; |
||||
noiseGeneratorAllPassL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorAllPassR[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayR[i] = new NoiseGenerator(sampleRate); |
||||
diffusionL[i] = new NoiseGenerator(sampleRate); |
||||
diffusionR[i] = new NoiseGenerator(sampleRate); |
||||
} |
||||
|
||||
preAllPassFilterL = new AllPassFilter(180.0f, 0.68f, sampleRate); |
||||
preAllPassFilterR = new AllPassFilter(180.0f, 0.68f, sampleRate); |
||||
|
||||
postAllPassFilterL = new AllPassFilter(220.0f, 0.68f, sampleRate); |
||||
postAllPassFilterR = new AllPassFilter(220.0f, 0.68f, sampleRate); |
||||
|
||||
allPassFiltersL = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
allPassFiltersR = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
allPassFiltersL[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.1f, 0.68f, sampleRate); |
||||
allPassFiltersR[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.1f, 0.68f, sampleRate); |
||||
} |
||||
|
||||
talEqL = new TalEq(sampleRate); |
||||
talEqR = new TalEq(sampleRate); |
||||
|
||||
decayTime = 0.5f; |
||||
preDelayTime = 0.0f; |
||||
modulationIntensity = 0.12f; |
||||
stereoMode = false; |
||||
|
||||
outL = 0.0f; |
||||
outR = 0.0f; |
||||
|
||||
feedbackValueL = 0.0f; |
||||
feedbackValueR = 0.0f; |
||||
} |
||||
|
||||
~Reverb() |
||||
{ |
||||
delete[] reflectionGains; |
||||
delete[] reflectionDelays; |
||||
|
||||
delete combFiltersPreDelayL; |
||||
delete combFiltersPreDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersL[i]; |
||||
delete[] combFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersR[i]; |
||||
delete[] combFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersL[i]; |
||||
delete[] allPassFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersR[i]; |
||||
delete[] allPassFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassL[i]; |
||||
delete[] noiseGeneratorAllPassL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassR[i]; |
||||
delete[] noiseGeneratorAllPassR; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayL[i]; |
||||
delete[] noiseGeneratorDelayL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayR[i]; |
||||
delete[] noiseGeneratorDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionL[i]; |
||||
delete[] diffusionL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionR[i]; |
||||
delete[] diffusionR; |
||||
|
||||
delete preAllPassFilterL; |
||||
delete preAllPassFilterR; |
||||
|
||||
delete postAllPassFilterL; |
||||
delete postAllPassFilterR; |
||||
|
||||
delete talEqL; |
||||
delete talEqR; |
||||
} |
||||
|
||||
|
||||
void setDecayTime(float decayTime) |
||||
{ |
||||
this->decayTime = audioUtils.getLogScaledValueInverted(decayTime) * 0.99f; |
||||
} |
||||
|
||||
void setPreDelay(float preDelayTime) |
||||
{ |
||||
this->preDelayTime = audioUtils.getLogScaledValue(preDelayTime); |
||||
} |
||||
|
||||
void setStereoMode(bool stereoMode) |
||||
{ |
||||
this->stereoMode = stereoMode; |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
talEqL->setLowShelfGain(lowShelfGain); |
||||
talEqR->setLowShelfGain(lowShelfGain); |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
talEqL->setHighShelfGain(highShelfGain); |
||||
talEqR->setHighShelfGain(highShelfGain); |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
talEqL->setLowShelfFrequency(lowShelfFrequency); |
||||
talEqR->setLowShelfFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
talEqL->setHighShelfFrequency(highShelfFrequency); |
||||
talEqR->setHighShelfFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
// All input values [0..1]
|
||||
inline void process(float* sampleL, float* sampleR) |
||||
{ |
||||
float revL = 0.0f; |
||||
float revR = 0.0f; |
||||
|
||||
if (!stereoMode) |
||||
{ |
||||
revL += (*sampleL + *sampleR) * 0.125f;
|
||||
revL += combFiltersPreDelayL->process(revL, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
revR = revL; |
||||
} |
||||
else |
||||
{ |
||||
revL += combFiltersPreDelayL->process(*sampleL * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
revR += combFiltersPreDelayR->process(*sampleR * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
talEqR->process(&revR); |
||||
} |
||||
|
||||
// ----------------- Comb Filter --------------------
|
||||
outL = feedbackValueL * 0.1f; |
||||
outR = feedbackValueR * 0.1f; |
||||
|
||||
float scaledRoomSize = decayTime * 0.979f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{
|
||||
outL += combFiltersL[i]->processInterpolated(revL, diffusionL[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.02f * noiseGeneratorDelayL[i]->tickFilteredNoise()); |
||||
outR += combFiltersR[i]->processInterpolated(revR, diffusionR[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.02f * noiseGeneratorDelayR[i]->tickFilteredNoise()); |
||||
} |
||||
|
||||
// ----------------- Pre AllPass --------------------
|
||||
outL += 0.5f * preAllPassFilterL->processInterpolated(revL, scaledRoomSize * 0.99f + 0.01f * noiseGeneratorAllPassL[0]->tickFilteredNoise(), 0.0f, true); |
||||
outR += 0.5f * preAllPassFilterR->processInterpolated(revR, scaledRoomSize * 0.99f + 0.01f * noiseGeneratorAllPassR[0]->tickFilteredNoise(), 0.0f, true); |
||||
|
||||
// ----------------- Post AllPass --------------------
|
||||
outL += 0.1f * postAllPassFilterL->processInterpolated(outL, scaledRoomSize * 0.99f + 0.01f, 0.0f, false); |
||||
outR += 0.1f * postAllPassFilterR->processInterpolated(outR, scaledRoomSize * 0.99f + 0.01f, 0.0f, false); |
||||
|
||||
// ----------------- AllPass Filter ------------------
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
outL = allPassFiltersL[i]->process(outL); |
||||
outR = allPassFiltersR[i]->process(outR); |
||||
} |
||||
|
||||
// ----------------- Write to output / Stereo --------
|
||||
*sampleL = outL; |
||||
*sampleR = outR; |
||||
|
||||
feedbackValueL = outL; |
||||
feedbackValueR = outR; |
||||
} |
||||
|
||||
void createDelaysAndCoefficients(int numlines, float delayLength) |
||||
{ |
||||
reflectionDelays = new float[numlines]; |
||||
reflectionGains = new float[numlines]; |
||||
|
||||
float volumeScale = (float)(-3.0 * delayLength / log10f(0.5f)); |
||||
for (int n = numlines - 1; n >= 0; n--) |
||||
{ |
||||
reflectionDelays[numlines -1 - n] = delayLength / powf(2.0f, (float)n / numlines);
|
||||
reflectionGains[numlines -1 - n] = powf(10.0f, - (3.0f * reflectionDelays[numlines -1 - n]) / volumeScale); |
||||
} |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,303 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
|
||||
#if !defined(__Reverb_h) |
||||
#define __Reverb_h |
||||
|
||||
#include "AllPassFilter.h" |
||||
#include "CombFilter.h" |
||||
#include "NoiseGenerator.h" |
||||
#include "Filter.h" |
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
#include "TalEq.h" |
||||
|
||||
class Reverb |
||||
{ |
||||
private: |
||||
static const int DELAY_LINES_COMB = 4; |
||||
static const int DELAY_LINES_ALLPASS = 5; |
||||
|
||||
static const int MAX_PRE_DELAY_MS = 1000; |
||||
float* reflectionGains; |
||||
float* reflectionDelays; |
||||
|
||||
CombFilter *combFiltersPreDelayL; |
||||
CombFilter *combFiltersPreDelayR; |
||||
|
||||
CombFilter **combFiltersL; |
||||
CombFilter **combFiltersR; |
||||
NoiseGenerator **noiseGeneratorAllPassL; |
||||
NoiseGenerator **noiseGeneratorAllPassR; |
||||
NoiseGenerator **noiseGeneratorDelayL; |
||||
NoiseGenerator **noiseGeneratorDelayR; |
||||
NoiseGenerator **diffusionL; |
||||
NoiseGenerator **diffusionR; |
||||
|
||||
AllPassFilter **allPassFiltersL; |
||||
AllPassFilter **allPassFiltersR; |
||||
|
||||
AllPassFilter *preAllPassFilterL; |
||||
AllPassFilter *preAllPassFilterR; |
||||
|
||||
AllPassFilter *postAllPassFilterL; |
||||
AllPassFilter *postAllPassFilterR; |
||||
|
||||
TalEq* talEqL; |
||||
TalEq* talEqR; |
||||
|
||||
float feedbackValueL; |
||||
float feedbackValueR; |
||||
|
||||
float decayTime; |
||||
float preDelayTime; |
||||
bool stereoMode; |
||||
float modulationIntensity; |
||||
|
||||
float outL; |
||||
float outR; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
Reverb(int sampleRate) |
||||
{ |
||||
createDelaysAndCoefficients(DELAY_LINES_COMB + DELAY_LINES_ALLPASS, 82.0f); |
||||
|
||||
combFiltersPreDelayL = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
combFiltersPreDelayR = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
|
||||
combFiltersL = new CombFilter *[DELAY_LINES_COMB]; |
||||
combFiltersR = new CombFilter *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
|
||||
float stereoSpreadValue = 0.008f; |
||||
float stereoSpreadSign = 1.0f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{ |
||||
float stereoSpreadFactor = 1.0f + stereoSpreadValue; |
||||
if (stereoSpreadSign > 0.0f) |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
} |
||||
else |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
} |
||||
stereoSpreadSign *= -1.0f; |
||||
noiseGeneratorAllPassL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorAllPassR[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayR[i] = new NoiseGenerator(sampleRate); |
||||
diffusionL[i] = new NoiseGenerator(sampleRate); |
||||
diffusionR[i] = new NoiseGenerator(sampleRate); |
||||
} |
||||
|
||||
preAllPassFilterL = new AllPassFilter(100.0f, 0.68f, sampleRate); |
||||
preAllPassFilterR = new AllPassFilter(100.0f, 0.68f, sampleRate); |
||||
|
||||
postAllPassFilterL = new AllPassFilter(80.0f, 0.68f, sampleRate); |
||||
postAllPassFilterR = new AllPassFilter(80.0f, 0.68f, sampleRate); |
||||
|
||||
allPassFiltersL = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
allPassFiltersR = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
allPassFiltersL[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.105f, 0.68f, sampleRate); |
||||
allPassFiltersR[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.1f, 0.68f, sampleRate); |
||||
} |
||||
|
||||
talEqL = new TalEq(sampleRate); |
||||
talEqR = new TalEq(sampleRate); |
||||
|
||||
decayTime = 0.5f; |
||||
preDelayTime = 0.0f; |
||||
modulationIntensity = 0.12f; |
||||
stereoMode = false; |
||||
|
||||
outL = 0.0f; |
||||
outR = 0.0f; |
||||
|
||||
feedbackValueL = 0.0f; |
||||
feedbackValueR = 0.0f; |
||||
} |
||||
|
||||
~Reverb() |
||||
{ |
||||
delete[] reflectionGains; |
||||
delete[] reflectionDelays; |
||||
|
||||
delete combFiltersPreDelayL; |
||||
delete combFiltersPreDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersL[i]; |
||||
delete[] combFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersR[i]; |
||||
delete[] combFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersL[i]; |
||||
delete[] allPassFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersR[i]; |
||||
delete[] allPassFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassL[i]; |
||||
delete[] noiseGeneratorAllPassL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassR[i]; |
||||
delete[] noiseGeneratorAllPassR; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayL[i]; |
||||
delete[] noiseGeneratorDelayL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayR[i]; |
||||
delete[] noiseGeneratorDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionL[i]; |
||||
delete[] diffusionL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionR[i]; |
||||
delete[] diffusionR; |
||||
|
||||
delete preAllPassFilterL; |
||||
delete preAllPassFilterR; |
||||
|
||||
delete postAllPassFilterL; |
||||
delete postAllPassFilterR; |
||||
|
||||
delete talEqL; |
||||
delete talEqR; |
||||
} |
||||
|
||||
|
||||
void setDecayTime(float decayTime) |
||||
{ |
||||
this->decayTime = audioUtils.getLogScaledValueInverted(decayTime) * 0.99f; |
||||
} |
||||
|
||||
void setPreDelay(float preDelayTime) |
||||
{ |
||||
this->preDelayTime = audioUtils.getLogScaledValue(preDelayTime); |
||||
} |
||||
|
||||
void setStereoMode(bool stereoMode) |
||||
{ |
||||
this->stereoMode = stereoMode; |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
talEqL->setLowShelfGain(lowShelfGain); |
||||
talEqR->setLowShelfGain(lowShelfGain); |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
talEqL->setHighShelfGain(highShelfGain); |
||||
talEqR->setHighShelfGain(highShelfGain); |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
talEqL->setLowShelfFrequency(lowShelfFrequency); |
||||
talEqR->setLowShelfFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
talEqL->setHighShelfFrequency(highShelfFrequency); |
||||
talEqR->setHighShelfFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
// All input values [0..1]
|
||||
inline void process(float* sampleL, float* sampleR) |
||||
{ |
||||
float revL = 0.0f; |
||||
float revR = 0.0f; |
||||
|
||||
if (!stereoMode) |
||||
{ |
||||
revL += (*sampleL + *sampleR) * 0.125f;
|
||||
revL += combFiltersPreDelayL->process(revL, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
revR = revL; |
||||
} |
||||
else |
||||
{ |
||||
revL += combFiltersPreDelayL->process(*sampleL * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
revR += combFiltersPreDelayR->process(*sampleR * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
talEqR->process(&revR); |
||||
} |
||||
|
||||
// ----------------- Comb Filter --------------------
|
||||
outL = feedbackValueL * 0.05f; |
||||
outR = feedbackValueR * 0.05f; |
||||
|
||||
float scaledRoomSize = decayTime * 0.99f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{
|
||||
outL += combFiltersL[i]->processInterpolated(revL, diffusionL[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.01f * noiseGeneratorDelayL[i]->tickFilteredNoise()); |
||||
outR += combFiltersR[i]->processInterpolated(revR, diffusionR[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.01f * noiseGeneratorDelayR[i]->tickFilteredNoise()); |
||||
} |
||||
|
||||
// ----------------- Pre AllPass --------------------
|
||||
float invAllPassL = 0.1f * preAllPassFilterL->processInterpolated(revL, 0.99f + 0.01f * noiseGeneratorAllPassL[0]->tickFilteredNoiseFast(), 0.68f, true); |
||||
float invAllPassR = 0.1f * preAllPassFilterR->processInterpolated(revR, 0.99f + 0.01f * noiseGeneratorAllPassR[0]->tickFilteredNoiseFast(), 0.68f, true); |
||||
|
||||
//// ----------------- Post AllPass --------------------
|
||||
outL += 0.15f * postAllPassFilterL->processInterpolated(invAllPassL, 0.99f + 0.01f, 0.68f, false); |
||||
outR += 0.15f * postAllPassFilterR->processInterpolated(invAllPassR, 0.99f + 0.01f, 0.68f, false); |
||||
|
||||
// ----------------- AllPass Filter ------------------
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
outL = allPassFiltersL[i]->process(outL); |
||||
outR = allPassFiltersR[i]->process(outR); |
||||
} |
||||
|
||||
// ----------------- Write to output / Stereo --------
|
||||
*sampleL = outL; |
||||
*sampleR = outR; |
||||
|
||||
feedbackValueL = outL; |
||||
feedbackValueR = outR; |
||||
} |
||||
|
||||
void createDelaysAndCoefficients(int numlines, float delayLength) |
||||
{ |
||||
reflectionDelays = new float[numlines]; |
||||
reflectionGains = new float[numlines]; |
||||
|
||||
float volumeScale = (float)(-3.0 * delayLength / log10f(0.5f)); |
||||
for (int n = numlines - 1; n >= 0; n--) |
||||
{ |
||||
reflectionDelays[numlines -1 - n] = delayLength / powf(2.0f, (float)n / numlines);
|
||||
reflectionGains[numlines -1 - n] = powf(10.0f, - (3.0f * reflectionDelays[numlines -1 - n]) / volumeScale); |
||||
} |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,303 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
|
||||
#if !defined(__Reverb_h) |
||||
#define __Reverb_h |
||||
|
||||
#include "AllPassFilter.h" |
||||
#include "CombFilter.h" |
||||
#include "NoiseGenerator.h" |
||||
#include "Filter.h" |
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
#include "TalEq.h" |
||||
|
||||
class Reverb |
||||
{ |
||||
private: |
||||
static const int DELAY_LINES_COMB = 4; |
||||
static const int DELAY_LINES_ALLPASS = 5; |
||||
|
||||
static const int MAX_PRE_DELAY_MS = 1000; |
||||
float* reflectionGains; |
||||
float* reflectionDelays; |
||||
|
||||
CombFilter *combFiltersPreDelayL; |
||||
CombFilter *combFiltersPreDelayR; |
||||
|
||||
CombFilter **combFiltersL; |
||||
CombFilter **combFiltersR; |
||||
NoiseGenerator **noiseGeneratorAllPassL; |
||||
NoiseGenerator **noiseGeneratorAllPassR; |
||||
NoiseGenerator **noiseGeneratorDelayL; |
||||
NoiseGenerator **noiseGeneratorDelayR; |
||||
NoiseGenerator **diffusionL; |
||||
NoiseGenerator **diffusionR; |
||||
|
||||
AllPassFilter **allPassFiltersL; |
||||
AllPassFilter **allPassFiltersR; |
||||
|
||||
AllPassFilter *preAllPassFilterL; |
||||
AllPassFilter *preAllPassFilterR; |
||||
|
||||
AllPassFilter *postAllPassFilterL; |
||||
AllPassFilter *postAllPassFilterR; |
||||
|
||||
TalEq* talEqL; |
||||
TalEq* talEqR; |
||||
|
||||
float feedbackValueL; |
||||
float feedbackValueR; |
||||
|
||||
float decayTime; |
||||
float preDelayTime; |
||||
bool stereoMode; |
||||
float modulationIntensity; |
||||
|
||||
float outL; |
||||
float outR; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
Reverb(int sampleRate) |
||||
{ |
||||
createDelaysAndCoefficients(DELAY_LINES_COMB + DELAY_LINES_ALLPASS, 82.0f); |
||||
|
||||
combFiltersPreDelayL = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
combFiltersPreDelayR = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
|
||||
combFiltersL = new CombFilter *[DELAY_LINES_COMB]; |
||||
combFiltersR = new CombFilter *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorAllPassR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
noiseGeneratorDelayR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
diffusionR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
|
||||
float stereoSpreadValue = 0.008f; |
||||
float stereoSpreadSign = 1.0f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{ |
||||
float stereoSpreadFactor = 1.0f + stereoSpreadValue; |
||||
if (stereoSpreadSign > 0.0f) |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
} |
||||
else |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i], reflectionGains[i], sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, reflectionGains[i], sampleRate); |
||||
} |
||||
stereoSpreadSign *= -1.0f; |
||||
noiseGeneratorAllPassL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorAllPassR[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayL[i] = new NoiseGenerator(sampleRate); |
||||
noiseGeneratorDelayR[i] = new NoiseGenerator(sampleRate); |
||||
diffusionL[i] = new NoiseGenerator(sampleRate); |
||||
diffusionR[i] = new NoiseGenerator(sampleRate); |
||||
} |
||||
|
||||
preAllPassFilterL = new AllPassFilter(220.0f, 0.68f, sampleRate); |
||||
preAllPassFilterR = new AllPassFilter(220.0f, 0.68f, sampleRate); |
||||
|
||||
postAllPassFilterL = new AllPassFilter(180.0f, 0.68f, sampleRate); |
||||
postAllPassFilterR = new AllPassFilter(180.0f, 0.68f, sampleRate); |
||||
|
||||
allPassFiltersL = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
allPassFiltersR = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
allPassFiltersL[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.2f, 0.68f, sampleRate); |
||||
allPassFiltersR[i] = new AllPassFilter(reflectionDelays[i + DELAY_LINES_COMB - 1] * 0.2f, 0.68f, sampleRate); |
||||
} |
||||
|
||||
talEqL = new TalEq(sampleRate); |
||||
talEqR = new TalEq(sampleRate); |
||||
|
||||
decayTime = 0.5f; |
||||
preDelayTime = 0.0f; |
||||
modulationIntensity = 0.12f; |
||||
stereoMode = false; |
||||
|
||||
outL = 0.0f; |
||||
outR = 0.0f; |
||||
|
||||
feedbackValueL = 0.0f; |
||||
feedbackValueR = 0.0f; |
||||
} |
||||
|
||||
~Reverb() |
||||
{ |
||||
delete[] reflectionGains; |
||||
delete[] reflectionDelays; |
||||
|
||||
delete combFiltersPreDelayL; |
||||
delete combFiltersPreDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersL[i]; |
||||
delete[] combFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersR[i]; |
||||
delete[] combFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersL[i]; |
||||
delete[] allPassFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersR[i]; |
||||
delete[] allPassFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassL[i]; |
||||
delete[] noiseGeneratorAllPassL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassR[i]; |
||||
delete[] noiseGeneratorAllPassR; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayL[i]; |
||||
delete[] noiseGeneratorDelayL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayR[i]; |
||||
delete[] noiseGeneratorDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionL[i]; |
||||
delete[] diffusionL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionR[i]; |
||||
delete[] diffusionR; |
||||
|
||||
delete preAllPassFilterL; |
||||
delete preAllPassFilterR; |
||||
|
||||
delete postAllPassFilterL; |
||||
delete postAllPassFilterR; |
||||
|
||||
delete talEqL; |
||||
delete talEqR; |
||||
} |
||||
|
||||
|
||||
void setDecayTime(float decayTime) |
||||
{ |
||||
this->decayTime = audioUtils.getLogScaledValueInverted(decayTime) * 0.99f; |
||||
} |
||||
|
||||
void setPreDelay(float preDelayTime) |
||||
{ |
||||
this->preDelayTime = audioUtils.getLogScaledValue(preDelayTime); |
||||
} |
||||
|
||||
void setStereoMode(bool stereoMode) |
||||
{ |
||||
this->stereoMode = stereoMode; |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
talEqL->setLowShelfGain(lowShelfGain); |
||||
talEqR->setLowShelfGain(lowShelfGain); |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
talEqL->setHighShelfGain(highShelfGain); |
||||
talEqR->setHighShelfGain(highShelfGain); |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
talEqL->setLowShelfFrequency(lowShelfFrequency); |
||||
talEqR->setLowShelfFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
talEqL->setHighShelfFrequency(highShelfFrequency); |
||||
talEqR->setHighShelfFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
// All input values [0..1]
|
||||
inline void process(float* sampleL, float* sampleR) |
||||
{ |
||||
float revL = 0.0f; |
||||
float revR = 0.0f; |
||||
|
||||
if (!stereoMode) |
||||
{ |
||||
revL += (*sampleL + *sampleR) * 0.125f;
|
||||
revL += combFiltersPreDelayL->process(revL, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
revR = revL; |
||||
} |
||||
else |
||||
{ |
||||
revL += combFiltersPreDelayL->process(*sampleL * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
revR += combFiltersPreDelayR->process(*sampleR * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
talEqR->process(&revR); |
||||
} |
||||
|
||||
// ----------------- Comb Filter --------------------
|
||||
outL = feedbackValueL * 0.05f; |
||||
outR = feedbackValueR * 0.05f; |
||||
|
||||
float scaledRoomSize = decayTime * 0.97f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{
|
||||
outL += combFiltersL[i]->processInterpolated(revL, diffusionL[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.035f * noiseGeneratorDelayL[i]->tickFilteredNoise()); |
||||
outR += combFiltersR[i]->processInterpolated(revR, diffusionR[i]->tickFilteredNoiseFast() * 0.01f, scaledRoomSize, scaledRoomSize + 0.035f * noiseGeneratorDelayR[i]->tickFilteredNoise()); |
||||
} |
||||
|
||||
// ----------------- Pre AllPass --------------------
|
||||
float modL = preAllPassFilterL->processInterpolated(outL, decayTime * decayTime * 0.999f + 0.001f * noiseGeneratorAllPassL[0]->tickFilteredNoise(), 0.68f, true); |
||||
float modR = preAllPassFilterR->processInterpolated(outR, decayTime * decayTime * 0.999f + 0.001f * noiseGeneratorAllPassR[0]->tickFilteredNoise(), 0.68f, true); |
||||
|
||||
// ----------------- Post AllPass --------------------
|
||||
outL += 0.3f * postAllPassFilterL->processInterpolated(modL, decayTime * decayTime * 1.0f, 0.68f, false); |
||||
outR += 0.3f * postAllPassFilterR->processInterpolated(modR, decayTime * decayTime * 1.0f, 0.68f, false); |
||||
|
||||
// ----------------- AllPass Filter ------------------
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
outL = allPassFiltersL[i]->process(outL); |
||||
outR = allPassFiltersR[i]->process(outR); |
||||
} |
||||
|
||||
// ----------------- Write to output / Stereo --------
|
||||
*sampleL = outL; |
||||
*sampleR = outR; |
||||
|
||||
feedbackValueL = outL; |
||||
feedbackValueR = outR; |
||||
} |
||||
|
||||
void createDelaysAndCoefficients(int numlines, float delayLength) |
||||
{ |
||||
reflectionDelays = new float[numlines]; |
||||
reflectionGains = new float[numlines]; |
||||
|
||||
float volumeScale = (float)(-3.0 * delayLength / log10f(0.5f)); |
||||
for (int n = numlines - 1; n >= 0; n--) |
||||
{ |
||||
reflectionDelays[numlines -1 - n] = delayLength / powf(2.0f, (float)n / numlines);
|
||||
reflectionGains[numlines -1 - n] = powf(10.0f, - (3.0f * reflectionDelays[numlines -1 - n]) / volumeScale); |
||||
} |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,316 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__TalReverb_h) |
||||
#define __TalReverb_h |
||||
|
||||
#include "AllPassFilter.h" |
||||
#include "CombFilter.h" |
||||
#include "NoiseGenerator.h" |
||||
#include "Filter.h" |
||||
#include "math.h" |
||||
#include "AudioUtils.h" |
||||
#include "TalEq.h" |
||||
|
||||
class TalReverb |
||||
{ |
||||
private: |
||||
static const int DELAY_LINES_COMB = 4; |
||||
static const int DELAY_LINES_ALLPASS = 5; |
||||
|
||||
static const int MAX_PRE_DELAY_MS = 1000; |
||||
float* reflectionGains; |
||||
float* reflectionDelays; |
||||
|
||||
CombFilter *combFiltersPreDelayL; |
||||
CombFilter *combFiltersPreDelayR; |
||||
|
||||
CombFilter **combFiltersL; |
||||
CombFilter **combFiltersR; |
||||
NoiseGenerator **noiseGeneratorAllPassL; |
||||
NoiseGenerator **noiseGeneratorAllPassR; |
||||
NoiseGenerator **noiseGeneratorDelayL; |
||||
NoiseGenerator **noiseGeneratorDelayR; |
||||
NoiseGenerator **diffusionL; |
||||
NoiseGenerator **diffusionR; |
||||
|
||||
AllPassFilter **allPassFiltersL; |
||||
AllPassFilter **allPassFiltersR; |
||||
|
||||
AllPassFilter *preAllPassFilterL; |
||||
AllPassFilter *preAllPassFilterR; |
||||
|
||||
AllPassFilter *postAllPassFilterL; |
||||
AllPassFilter *postAllPassFilterR; |
||||
|
||||
TalEq* talEqL; |
||||
TalEq* talEqR; |
||||
|
||||
float feedbackValueL; |
||||
float feedbackValueR; |
||||
|
||||
float decayTime; |
||||
float preDelayTime; |
||||
bool stereoMode; |
||||
float modulationIntensity; |
||||
|
||||
float outL; |
||||
float outR; |
||||
|
||||
float feedbackSampleRateFactor; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
TalReverb(long sampleRate) |
||||
{ |
||||
// Ignore sample rates smaller then 44100 Hz
|
||||
this->feedbackSampleRateFactor = sampleRate / 44100.0f; |
||||
if (this->feedbackSampleRateFactor < 1.0f) this->feedbackSampleRateFactor = 1.0f; |
||||
|
||||
this->createDelaysAndCoefficients(DELAY_LINES_ALLPASS, 100.0f); |
||||
|
||||
this->combFiltersPreDelayL = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
this->combFiltersPreDelayR = new CombFilter((float)MAX_PRE_DELAY_MS, 0.0f, sampleRate); |
||||
|
||||
this->combFiltersL = new CombFilter *[DELAY_LINES_COMB]; |
||||
this->combFiltersR = new CombFilter *[DELAY_LINES_COMB]; |
||||
this->noiseGeneratorAllPassL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
this->noiseGeneratorAllPassR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
this->noiseGeneratorDelayL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
this->noiseGeneratorDelayR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
this->diffusionL = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
this->diffusionR = new NoiseGenerator *[DELAY_LINES_COMB]; |
||||
|
||||
float stereoSpreadValue = 0.008f; |
||||
float stereoSpreadSign = 1.0f; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{ |
||||
float stereoSpreadFactor = 1.0f + stereoSpreadValue; |
||||
if (stereoSpreadSign > 0.0f) |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, 1.0f, sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i], 1.0f, sampleRate); |
||||
} |
||||
else |
||||
{ |
||||
combFiltersL[i] = new CombFilter(reflectionDelays[i], 1.0f, sampleRate); |
||||
combFiltersR[i] = new CombFilter(reflectionDelays[i] * stereoSpreadFactor, 1.0f, sampleRate); |
||||
} |
||||
stereoSpreadSign *= -1.0f; |
||||
|
||||
this->noiseGeneratorAllPassL[i] = new NoiseGenerator((float)sampleRate, (float)i); |
||||
this->noiseGeneratorAllPassR[i] = new NoiseGenerator((float)sampleRate, i + 163.0f); |
||||
this->noiseGeneratorDelayL[i] = new NoiseGenerator((float)sampleRate, i + 257.0f); |
||||
this->noiseGeneratorDelayR[i] = new NoiseGenerator((float)sampleRate, i + 353.0f); |
||||
this->diffusionL[i] = new NoiseGenerator((float)sampleRate, i + 455.0f); |
||||
this->diffusionR[i] = new NoiseGenerator((float)sampleRate, i + 633.0f); |
||||
} |
||||
|
||||
this->preAllPassFilterL = new AllPassFilter(90.0f, 0.68f, sampleRate); |
||||
this->preAllPassFilterR = new AllPassFilter(90.0f, 0.68f, sampleRate); |
||||
|
||||
this->postAllPassFilterL = new AllPassFilter(91.0f, 0.68f, sampleRate); |
||||
this->postAllPassFilterR = new AllPassFilter(91.0f, 0.68f, sampleRate); |
||||
|
||||
this->allPassFiltersL = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
this->allPassFiltersR = new AllPassFilter *[DELAY_LINES_ALLPASS]; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
this->allPassFiltersL[i] = new AllPassFilter(reflectionDelays[i] * 0.2f, 0.68f, sampleRate); |
||||
this->allPassFiltersR[i] = new AllPassFilter(reflectionDelays[i] * 0.2f, 0.68f, sampleRate); |
||||
} |
||||
|
||||
this->talEqL = new TalEq((float)sampleRate); |
||||
this->talEqR = new TalEq((float)sampleRate); |
||||
|
||||
this->decayTime = 0.5f; |
||||
this->preDelayTime = 0.0f; |
||||
this->modulationIntensity = 0.12f; |
||||
this->stereoMode = false; |
||||
|
||||
this->outL = 0.0f; |
||||
this->outR = 0.0f; |
||||
|
||||
this->feedbackValueL = 0.0f; |
||||
this->feedbackValueR = 0.0f; |
||||
} |
||||
|
||||
~TalReverb() |
||||
{ |
||||
delete[] reflectionGains; |
||||
delete[] reflectionDelays; |
||||
|
||||
delete combFiltersPreDelayL; |
||||
delete combFiltersPreDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersL[i]; |
||||
delete[] combFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete combFiltersR[i]; |
||||
delete[] combFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersL[i]; |
||||
delete[] allPassFiltersL; |
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) delete allPassFiltersR[i]; |
||||
delete[] allPassFiltersR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassL[i]; |
||||
delete[] noiseGeneratorAllPassL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorAllPassR[i]; |
||||
delete[] noiseGeneratorAllPassR; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayL[i]; |
||||
delete[] noiseGeneratorDelayL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete noiseGeneratorDelayR[i]; |
||||
delete[] noiseGeneratorDelayR; |
||||
|
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionL[i]; |
||||
delete[] diffusionL; |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) delete diffusionR[i]; |
||||
delete[] diffusionR; |
||||
|
||||
delete preAllPassFilterL; |
||||
delete preAllPassFilterR; |
||||
|
||||
delete postAllPassFilterL; |
||||
delete postAllPassFilterR; |
||||
|
||||
delete talEqL; |
||||
delete talEqR; |
||||
} |
||||
|
||||
void setDecayTime(float decayTime) |
||||
{ |
||||
this->decayTime = audioUtils.getLogScaledValueInverted(decayTime) * 0.9f + 0.1f; |
||||
} |
||||
|
||||
void setPreDelay(float preDelayTime) |
||||
{ |
||||
this->preDelayTime = audioUtils.getLogScaledValue(preDelayTime); |
||||
} |
||||
|
||||
void setStereoMode(bool stereoMode) |
||||
{ |
||||
this->stereoMode = stereoMode; |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
talEqL->setLowShelfGain(lowShelfGain); |
||||
talEqR->setLowShelfGain(lowShelfGain); |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
talEqL->setHighShelfGain(highShelfGain); |
||||
talEqR->setHighShelfGain(highShelfGain); |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
talEqL->setLowShelfFrequency(lowShelfFrequency); |
||||
talEqR->setLowShelfFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
talEqL->setHighShelfFrequency(highShelfFrequency); |
||||
talEqR->setHighShelfFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
// All input values [0..1]
|
||||
inline void process(float* sampleL, float* sampleR) |
||||
{ |
||||
float revL = 0.0f; |
||||
float revR = 0.0f; |
||||
|
||||
if (!stereoMode) |
||||
{ |
||||
revL += (*sampleL + *sampleR) * 0.125f;
|
||||
revL += combFiltersPreDelayL->process(revL, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
revR = revL; |
||||
} |
||||
else |
||||
{ |
||||
revL += combFiltersPreDelayL->process(*sampleL * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
revR += combFiltersPreDelayR->process(*sampleR * 0.5f, 0.0f, 0.0f, preDelayTime); |
||||
talEqL->process(&revL); |
||||
talEqR->process(&revR); |
||||
} |
||||
|
||||
// ----------------- Comb Filter --------------------
|
||||
float feedbackFactor = 0.15f; |
||||
outL = feedbackValueL * feedbackFactor; |
||||
outR = feedbackValueR * feedbackFactor; |
||||
|
||||
float scaledRoomSizeDelay = this->decayTime * 0.972f; |
||||
float scaledRoomSizeDamp = this->decayTime * 0.99f; |
||||
float invDecayTime = 0.9f * (1.0f - this->decayTime); |
||||
for (int i = 0; i < DELAY_LINES_COMB; i++) |
||||
{
|
||||
outL += combFiltersL[i]->processInterpolated(revL, diffusionL[i]->tickFilteredNoiseFast() * invDecayTime, scaledRoomSizeDamp, scaledRoomSizeDelay + 0.028f * noiseGeneratorDelayL[i]->tickFilteredNoise()); |
||||
outR += combFiltersR[i]->processInterpolated(revR, diffusionR[i]->tickFilteredNoiseFast() * invDecayTime, scaledRoomSizeDamp, scaledRoomSizeDelay + 0.028f * noiseGeneratorDelayR[i]->tickFilteredNoise()); |
||||
} |
||||
|
||||
// ----------------- Pre AllPass --------------------
|
||||
float modL = preAllPassFilterL->processInterpolated(revL, 0.995f + 0.005f * noiseGeneratorAllPassL[0]->tickFilteredNoise(), 0.68f, true); |
||||
float modR = preAllPassFilterR->processInterpolated(revR, 0.995f + 0.005f * noiseGeneratorAllPassR[0]->tickFilteredNoise(), 0.68f, true); |
||||
|
||||
// ----------------- Post AllPass --------------------
|
||||
outL += 0.4f * postAllPassFilterL->processInterpolated(modL, decayTime, 0.68f, false); |
||||
outR += 0.4f * postAllPassFilterR->processInterpolated(modR, decayTime, 0.68f, false); |
||||
|
||||
// ----------------- AllPass Filter ------------------
|
||||
for (int i = 0; i < DELAY_LINES_ALLPASS; i++) |
||||
{ |
||||
outL = allPassFiltersL[i]->process(outL); |
||||
outR = allPassFiltersR[i]->process(outR); |
||||
} |
||||
|
||||
// ----------------- Write to output / Stereo --------
|
||||
//if (outL > 2.0f) outL = 2.0f;
|
||||
//if (outR > 2.0f) outR = 2.0f;
|
||||
//if (outL < -2.0f) outL = -2.0f;
|
||||
//if (outR < -2.0f) outR = -2.0f;
|
||||
|
||||
*sampleL = outL; |
||||
*sampleR = outR; |
||||
|
||||
feedbackValueL = outL; |
||||
feedbackValueR = outR; |
||||
} |
||||
|
||||
void createDelaysAndCoefficients(int numlines, float delayLength) |
||||
{ |
||||
this->reflectionDelays = new float[numlines]; |
||||
this->reflectionGains = new float[numlines]; |
||||
|
||||
float volumeScale = (float)(-3.0 * delayLength / log10f(0.55f)); |
||||
for (int n = numlines - 1; n >= 0; n--) |
||||
{ |
||||
reflectionDelays[numlines -1 - n] = delayLength / powf(2.0f, (float)n / numlines);
|
||||
reflectionGains[numlines -1 - n] = powf(10.0f, - (3.0f * reflectionDelays[numlines -1 - n]) / volumeScale); |
||||
} |
||||
} |
||||
}; |
||||
#endif |
@ -0,0 +1,232 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__ReverbEngine_h) |
||||
#define __ReverbEngine_h |
||||
|
||||
#include "Reverb.h" |
||||
#include "AudioUtils.h" |
||||
#include "Params.h" |
||||
#include "ParamChangeUtil.h" |
||||
#include "NoiseGenerator.h" |
||||
|
||||
class ReverbEngine
|
||||
{ |
||||
public: |
||||
float *param; |
||||
TalReverb* reverb; |
||||
|
||||
ParamChangeUtil* dryParamChange; |
||||
ParamChangeUtil* wetParamChange; |
||||
|
||||
NoiseGenerator *noiseGenerator; |
||||
|
||||
float dry; |
||||
float wet; |
||||
float stereoWidth; |
||||
float power; |
||||
|
||||
float* stereoVolumeWet; |
||||
float* stereoVolumeWetReturnValue; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
ReverbEngine(float sampleRate)
|
||||
{ |
||||
Params *params= new Params(); |
||||
this->param= params->parameters; |
||||
initialize(sampleRate); |
||||
} |
||||
|
||||
~ReverbEngine() |
||||
{ |
||||
delete reverb; |
||||
delete stereoVolumeWet; |
||||
delete noiseGenerator; |
||||
} |
||||
|
||||
void setDry(float dry) |
||||
{ |
||||
this->dry = audioUtils.getLogScaledVolume(dry, 2.0f); |
||||
} |
||||
|
||||
void setWet(float wet) |
||||
{ |
||||
this->wet = audioUtils.getLogScaledVolume(wet, 2.0f); |
||||
} |
||||
|
||||
void setDecayTime(float decayTime) |
||||
{ |
||||
float scaledDecayTime = audioUtils.getLogScaledValueInverted(decayTime); |
||||
reverb->setDecayTime(scaledDecayTime); |
||||
} |
||||
|
||||
void setPreDelay(float preDelay) |
||||
{ |
||||
reverb->setPreDelay(preDelay); |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
reverb->setLowShelfGain(lowShelfGain); |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
reverb->setHighShelfGain(highShelfGain); |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
reverb->setLowShelfFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
reverb->setHighShelfFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
void setStereoWidth(float stereoWidth) |
||||
{ |
||||
this->stereoWidth = stereoWidth; |
||||
} |
||||
|
||||
void setStereoMode(float stereoMode) |
||||
{ |
||||
reverb->setStereoMode(stereoMode > 0.0f ? true : false); |
||||
} |
||||
|
||||
void setSampleRate(float sampleRate) |
||||
{ |
||||
initialize(sampleRate); |
||||
} |
||||
|
||||
void setPower(float value) |
||||
{ |
||||
this->power = value; |
||||
} |
||||
|
||||
float* getCurrentVolume() |
||||
{ |
||||
stereoVolumeWetReturnValue[0] = stereoVolumeWet[0]; |
||||
stereoVolumeWetReturnValue[1] = stereoVolumeWet[1]; |
||||
|
||||
stereoVolumeWet[0] -= 0.01f; |
||||
stereoVolumeWet[1] -= 0.01f; |
||||
|
||||
if (stereoVolumeWet[0] < 0.0f) stereoVolumeWet[0] = 0.0f; |
||||
if (stereoVolumeWet[1] < 0.0f) stereoVolumeWet[1] = 0.0f; |
||||
|
||||
if (stereoVolumeWet[0] > 1.0f) stereoVolumeWet[0] = 1.0f; |
||||
if (stereoVolumeWet[1] > 1.0f) stereoVolumeWet[1] = 1.0f; |
||||
|
||||
return stereoVolumeWetReturnValue; |
||||
} |
||||
|
||||
void initialize(float sampleRate) |
||||
{ |
||||
if (sampleRate <= 0) |
||||
{ |
||||
sampleRate = 44100.0f; |
||||
} |
||||
|
||||
reverb = new TalReverb((int)sampleRate); |
||||
|
||||
dryParamChange = new ParamChangeUtil(sampleRate, 300.0f); |
||||
wetParamChange = new ParamChangeUtil(sampleRate, 300.0f); |
||||
|
||||
noiseGenerator = new NoiseGenerator(sampleRate, 1); |
||||
|
||||
stereoVolumeWet = new float[2]; |
||||
stereoVolumeWet[0] = 0.0f; |
||||
stereoVolumeWet[1] = 0.0f; |
||||
|
||||
stereoVolumeWetReturnValue = new float[2]; |
||||
stereoVolumeWetReturnValue[0] = 0.0f; |
||||
stereoVolumeWetReturnValue[1] = 0.0f; |
||||
|
||||
dry = 1.0f; |
||||
wet = 0.5f; |
||||
stereoWidth = 1.0f; |
||||
power = 1.0f; |
||||
} |
||||
|
||||
void process(float *sampleL, float *sampleR)
|
||||
{ |
||||
if (power > 0) |
||||
{ |
||||
// avoid cpu spikes
|
||||
float noise = noiseGenerator->tickNoise() * 0.000000001f; |
||||
|
||||
*sampleL += noise; |
||||
*sampleR += noise; |
||||
|
||||
float drysampleL = *sampleL; |
||||
float drysampleR = *sampleR; |
||||
|
||||
reverb->process(sampleL, sampleR); |
||||
|
||||
// Process Stereo
|
||||
float actualDryValue = dryParamChange->tick(dry); |
||||
float wet1 = wet * (stereoWidth * 0.5f + 0.5f); |
||||
float wet2 = wet * ((1.0f - stereoWidth) * 0.5f); |
||||
|
||||
float wetSignalL = *sampleL * wet1 + *sampleR * wet2; |
||||
float wetSignalR = *sampleR * wet1 + *sampleL * wet2; |
||||
|
||||
this->setMeterValue(wetSignalL, wetSignalR); |
||||
|
||||
float resultL = wetSignalL + drysampleL * actualDryValue; |
||||
float resultR = wetSignalR + drysampleR * actualDryValue; |
||||
*sampleL = resultL; |
||||
*sampleR = resultR; |
||||
} |
||||
else |
||||
{ |
||||
this->setMeterValue(0.0f, 0.0f); |
||||
} |
||||
} |
||||
|
||||
void setMeterValue(float valueL, float valueR) |
||||
{ |
||||
float absValueL = fabsf(valueL); |
||||
float absValueR = fabsf(valueR); |
||||
|
||||
if (absValueL >= stereoVolumeWet[0]) |
||||
{ |
||||
stereoVolumeWet[0] = absValueL; |
||||
} |
||||
|
||||
if (absValueR >= stereoVolumeWet[1]) |
||||
{ |
||||
stereoVolumeWet[1] = absValueR; |
||||
} |
||||
} |
||||
|
||||
void resetMeterValue() |
||||
{ |
||||
this->setMeterValue(0.0f, 0.0f); |
||||
} |
||||
}; |
||||
#endif |
||||
|
@ -0,0 +1,93 @@ |
||||
/*
|
||||
============================================================================== |
||||
This file is part of Tal-Reverb by Patrick Kunz. |
||||
|
||||
Copyright(c) 2005-2009 Patrick Kunz, TAL |
||||
Togu Audio Line, Inc. |
||||
http://kunz.corrupt.ch
|
||||
|
||||
This file may be licensed under the terms of of the |
||||
GNU General Public License Version 2 (the ``GPL''). |
||||
|
||||
Software distributed under the License is distributed |
||||
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either |
||||
express or implied. See the GPL for the specific language |
||||
governing rights and limitations. |
||||
|
||||
You should have received a copy of the GPL along with this |
||||
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
============================================================================== |
||||
*/ |
||||
|
||||
#if !defined(__TalEq_h) |
||||
#define __TalEq_h |
||||
|
||||
#include "HighShelf.h" |
||||
#include "LowShelf.h" |
||||
|
||||
class TalEq
|
||||
{ |
||||
private: |
||||
HighShelf *highShelf; |
||||
LowShelf *lowShelf; |
||||
|
||||
float lowShelfGain; |
||||
float highShelfGain; |
||||
|
||||
float lowShelfFrequency; |
||||
float highShelfFrequency; |
||||
|
||||
AudioUtils audioUtils; |
||||
|
||||
public: |
||||
TalEq(float sampleRate)
|
||||
{ |
||||
initialize(sampleRate); |
||||
} |
||||
|
||||
~TalEq() |
||||
{ |
||||
} |
||||
|
||||
void setLowShelfGain(float lowShelfGain) |
||||
{ |
||||
this->lowShelfGain = lowShelfGain * 0.5f; |
||||
} |
||||
|
||||
void setHighShelfGain(float highShelfGain) |
||||
{ |
||||
this->highShelfGain = highShelfGain * 0.5f; |
||||
} |
||||
|
||||
void setLowShelfFrequency(float lowShelfFrequency) |
||||
{ |
||||
this->lowShelfFrequency = audioUtils.getLogScaledFrequency(lowShelfFrequency); |
||||
} |
||||
|
||||
void setHighShelfFrequency(float highShelfFrequency) |
||||
{ |
||||
this->highShelfFrequency = audioUtils.getLogScaledFrequency(highShelfFrequency); |
||||
} |
||||
|
||||
void initialize(float sampleRate) |
||||
{ |
||||
highShelf = new HighShelf(sampleRate, 18); |
||||
lowShelf = new LowShelf(sampleRate, 18); |
||||
|
||||
lowShelfGain = 0.5f; |
||||
highShelfGain = 0.5f; |
||||
|
||||
lowShelfFrequency = 1000.0f; |
||||
highShelfFrequency = 200.0f; |
||||
} |
||||
|
||||
void process(float *sample)
|
||||
{ |
||||
highShelf->tick(sample, highShelfFrequency, 1.05f, highShelfGain); // 0..0.5
|
||||
lowShelf->tick(sample, lowShelfFrequency, 1.05f, lowShelfGain); // 0..0.5
|
||||
} |
||||
}; |
||||
#endif |
||||
|
Loading…
Reference in new issue