You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
MiniDexed/src/tal-reverb-3/Reverb.h

316 lines
11 KiB

/*
==============================================================================
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