mirror of
https://codeberg.org/armin/justasample.git
synced 2026-09-01 04:10:48 +02:00
init
This commit is contained in:
commit
d21bc831e1
178 changed files with 24136 additions and 0 deletions
237
External/Gin/gin_distortion.h
vendored
Normal file
237
External/Gin/gin_distortion.h
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the GIN library.
|
||||
Copyright (c) 2020 - Roland Rabien.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Chris Johnson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
|
||||
namespace gin
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Distortion based on AirWindows plugins
|
||||
*/
|
||||
class AirWindowsDistortion
|
||||
{
|
||||
public:
|
||||
AirWindowsDistortion()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void setSampleRate(double sr)
|
||||
{
|
||||
sampleRate = sr;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
A = 0.2f;
|
||||
B = 0.0f;
|
||||
C = 1.0f;
|
||||
D = 1.0f;
|
||||
iirSampleAL = 0.0f;
|
||||
iirSampleBL = 0.0f;
|
||||
iirSampleAR = 0.0f;
|
||||
iirSampleBR = 0.0f;
|
||||
fpFlip = true;
|
||||
fpNShapeL = 0.0f;
|
||||
fpNShapeR = 0.0f;
|
||||
}
|
||||
|
||||
void setParams(float density, float highpass, float output, float mix)
|
||||
{
|
||||
A = density;
|
||||
B = highpass;
|
||||
C = output;
|
||||
D = mix;
|
||||
}
|
||||
|
||||
void process(float* l, float* r, int sampleFrames)
|
||||
{
|
||||
double overallscale = 1.0;
|
||||
overallscale /= 44100.0;
|
||||
overallscale *= sampleRate;
|
||||
double density = (A * 5.0) - 1.0;
|
||||
double iirAmount = pow(B, 3) / overallscale;
|
||||
double output = C;
|
||||
double wet = D;
|
||||
double dry = 1.0 - wet;
|
||||
double bridgerectifier;
|
||||
double out = fabs(density);
|
||||
density = density * fabs(density);
|
||||
double count;
|
||||
|
||||
long double inputSampleL;
|
||||
long double inputSampleR;
|
||||
long double drySampleL;
|
||||
long double drySampleR;
|
||||
|
||||
while (--sampleFrames >= 0)
|
||||
{
|
||||
inputSampleL = *l;
|
||||
inputSampleR = *r;
|
||||
if (inputSampleL < 1.2e-38 && -inputSampleL < 1.2e-38) {
|
||||
static int noisesource = 0;
|
||||
//this declares a variable before anything else is compiled. It won't keep assigning
|
||||
//it to 0 for every sample, it's as if the declaration doesn't exist in this context,
|
||||
//but it lets me add this denormalization fix in a single place rather than updating
|
||||
//it in three different locations. The variable isn't thread-safe but this is only
|
||||
//a random seed and we can share it with whatever.
|
||||
noisesource = noisesource % 1700021; noisesource++;
|
||||
int residue = noisesource * noisesource;
|
||||
residue = residue % 170003; residue *= residue;
|
||||
residue = residue % 17011; residue *= residue;
|
||||
residue = residue % 1709; residue *= residue;
|
||||
residue = residue % 173; residue *= residue;
|
||||
residue = residue % 17;
|
||||
double applyresidue = residue;
|
||||
applyresidue *= 0.00000001;
|
||||
applyresidue *= 0.00000001;
|
||||
inputSampleL = applyresidue;
|
||||
}
|
||||
if (inputSampleR < 1.2e-38 && -inputSampleR < 1.2e-38) {
|
||||
static int noisesource = 0;
|
||||
noisesource = noisesource % 1700021; noisesource++;
|
||||
int residue = noisesource * noisesource;
|
||||
residue = residue % 170003; residue *= residue;
|
||||
residue = residue % 17011; residue *= residue;
|
||||
residue = residue % 1709; residue *= residue;
|
||||
residue = residue % 173; residue *= residue;
|
||||
residue = residue % 17;
|
||||
double applyresidue = residue;
|
||||
applyresidue *= 0.00000001;
|
||||
applyresidue *= 0.00000001;
|
||||
inputSampleR = applyresidue;
|
||||
//this denormalization routine produces a white noise at -300 dB which the noise
|
||||
//shaping will interact with to produce a bipolar output, but the noise is actually
|
||||
//all positive. That should stop any variables from going denormal, and the routine
|
||||
//only kicks in if digital black is input. As a final touch, if you save to 24-bit
|
||||
//the silence will return to being digital black again.
|
||||
}
|
||||
drySampleL = inputSampleL;
|
||||
drySampleR = inputSampleR;
|
||||
|
||||
if (fpFlip)
|
||||
{
|
||||
iirSampleAL = double((iirSampleAL * (1.0 - iirAmount)) + (inputSampleL * iirAmount));
|
||||
inputSampleL -= iirSampleAL;
|
||||
iirSampleAR = double((iirSampleAR * (1.0 - iirAmount)) + (inputSampleR * iirAmount));
|
||||
inputSampleR -= iirSampleAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
iirSampleBL = double((iirSampleBL * (1.0 - iirAmount)) + (inputSampleL * iirAmount));
|
||||
inputSampleL -= iirSampleBL;
|
||||
iirSampleBR = double((iirSampleBR * (1.0 - iirAmount)) + (inputSampleR * iirAmount));
|
||||
inputSampleR -= iirSampleBR;
|
||||
}
|
||||
//highpass section
|
||||
fpFlip = !fpFlip;
|
||||
|
||||
count = density;
|
||||
while (count > 1.0)
|
||||
{
|
||||
bridgerectifier = double(fabs(inputSampleL) * 1.57079633);
|
||||
if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
|
||||
//max value for sine function
|
||||
bridgerectifier = sin(bridgerectifier);
|
||||
if (inputSampleL > 0.0) inputSampleL = bridgerectifier;
|
||||
else inputSampleL = -bridgerectifier;
|
||||
|
||||
bridgerectifier = double(fabs(inputSampleR) * 1.57079633);
|
||||
if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
|
||||
//max value for sine function
|
||||
bridgerectifier = sin(bridgerectifier);
|
||||
if (inputSampleR > 0.0) inputSampleR = bridgerectifier;
|
||||
else inputSampleR = -bridgerectifier;
|
||||
|
||||
count = count - 1.0;
|
||||
}
|
||||
//we have now accounted for any really high density settings.
|
||||
|
||||
while (out > 1.0) out = out - 1.0;
|
||||
|
||||
bridgerectifier = double(fabs(inputSampleL) * 1.57079633);
|
||||
if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
|
||||
//max value for sine function
|
||||
if (density > 0) bridgerectifier = sin(bridgerectifier);
|
||||
else bridgerectifier = 1 - cos(bridgerectifier);
|
||||
//produce either boosted or starved version
|
||||
if (inputSampleL > 0) inputSampleL = (inputSampleL * (1 - out)) + (bridgerectifier * out);
|
||||
else inputSampleL = (inputSampleL * (1 - out)) - (bridgerectifier * out);
|
||||
//blend according to density control
|
||||
|
||||
bridgerectifier = double(fabs(inputSampleR) * 1.57079633);
|
||||
if (bridgerectifier > 1.57079633) bridgerectifier = 1.57079633;
|
||||
//max value for sine function
|
||||
if (density > 0) bridgerectifier = sin(bridgerectifier);
|
||||
else bridgerectifier = 1 - cos(bridgerectifier);
|
||||
//produce either boosted or starved version
|
||||
if (inputSampleR > 0) inputSampleR = (inputSampleR * (1.0 - out)) + (bridgerectifier * out);
|
||||
else inputSampleR = (inputSampleR * (1.0 - out)) - (bridgerectifier * out);
|
||||
//blend according to density control
|
||||
|
||||
if (output < 1.0) {
|
||||
inputSampleL *= output;
|
||||
inputSampleR *= output;
|
||||
}
|
||||
if (wet < 1.0) {
|
||||
inputSampleL = (drySampleL * dry) + (inputSampleL * wet);
|
||||
inputSampleR = (drySampleR * dry) + (inputSampleR * wet);
|
||||
}
|
||||
//nice little output stage template: if we have another scale of floating point
|
||||
//number, we really don't want to meaninglessly multiply that by 1.0.
|
||||
|
||||
//stereo 32 bit dither, made small and tidy.
|
||||
int expon; frexpf((float)inputSampleL, &expon);
|
||||
long double dither = (rand() / (RAND_MAX * 7.737125245533627e+25)) * pow(2, expon + 62);
|
||||
inputSampleL += (dither - fpNShapeL); fpNShapeL = dither;
|
||||
frexpf((float)inputSampleR, &expon);
|
||||
dither = (rand() / (RAND_MAX * 7.737125245533627e+25)) * pow(2, expon + 62);
|
||||
inputSampleR += (dither - fpNShapeR); fpNShapeR = dither;
|
||||
//end 32 bit dither
|
||||
|
||||
*l = float(inputSampleL);
|
||||
*r = float(inputSampleR);
|
||||
|
||||
l++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
double sampleRate = 44100.0;
|
||||
long double fpNShapeL, fpNShapeR;
|
||||
double iirSampleAL, iirSampleBL, iirSampleAR, iirSampleBR;
|
||||
bool fpFlip;
|
||||
float A, B, C, D;
|
||||
};
|
||||
} // namespace gin
|
||||
328
External/Gin/gin_simpleverb.cpp
vendored
Normal file
328
External/Gin/gin_simpleverb.cpp
vendored
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the GIN library.
|
||||
Copyright (c) 2019 - Roland Rabien.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "gin_simpleverb.h"
|
||||
|
||||
gin::SimpleVerb::SimpleVerb()
|
||||
{
|
||||
roomSizeFader = 0.5;
|
||||
roomSize = 55;
|
||||
|
||||
preDelayFader = 0;
|
||||
|
||||
preDelayLength = 0;
|
||||
preDelayPos = 0;
|
||||
|
||||
dampFader = 0.5;
|
||||
damp = 0.25;
|
||||
|
||||
freqLPFader = 1;
|
||||
freqHPFader = 0;
|
||||
|
||||
freqLP = 24000;
|
||||
freqHP = 0;
|
||||
|
||||
b1LP = -std::exp(-2.0f * juce::MathConstants<float>::pi * freqLP / sampleRate); // 100Hz
|
||||
a0LP = 1.0f + b1LP;
|
||||
|
||||
b1HP = -std::exp(-2.0f * juce::MathConstants<float>::pi * freqHP / sampleRate); // 100Hz
|
||||
a0HP = 1.0f + b1HP;
|
||||
|
||||
dry = 1;
|
||||
wet = 0.5;
|
||||
|
||||
setSampleRate(44100);
|
||||
}
|
||||
|
||||
void gin::SimpleVerb::setSampleRate(float sr)
|
||||
{
|
||||
constexpr float roomMaxSize = 100.0f;
|
||||
|
||||
sampleRate = sr;
|
||||
|
||||
auto comb1MaxLength = static_cast<unsigned int>(C1 * roomMaxSize * sampleRate / 1000);
|
||||
comb1.resize(comb1MaxLength);
|
||||
auto comb2MaxLength = static_cast<unsigned int>(C2 * roomMaxSize * sampleRate / 1000);
|
||||
comb2.resize(comb2MaxLength);
|
||||
auto comb3MaxLength = static_cast<unsigned int>(C3 * roomMaxSize * sampleRate / 1000);
|
||||
comb3.resize(comb3MaxLength);
|
||||
auto comb4MaxLength = static_cast<unsigned int>(C4 * roomMaxSize * sampleRate / 1000);
|
||||
comb4.resize(comb4MaxLength);
|
||||
auto comb5MaxLength = static_cast<unsigned int>(C5 * roomMaxSize * sampleRate / 1000);
|
||||
comb5.resize(comb5MaxLength);
|
||||
auto comb6MaxLength = static_cast<unsigned int>(C6 * roomMaxSize * sampleRate / 1000);
|
||||
comb6.resize(comb6MaxLength);
|
||||
auto comb7MaxLength = static_cast<unsigned int>(C7 * roomMaxSize * sampleRate / 1000);
|
||||
comb7.resize(comb7MaxLength);
|
||||
auto comb8MaxLength = static_cast<unsigned int>(C8 * roomMaxSize * sampleRate / 1000);
|
||||
comb8.resize(comb8MaxLength);
|
||||
auto comb9MaxLength = static_cast<unsigned int>(C9 * roomMaxSize * sampleRate / 1000);
|
||||
comb9.resize(comb9MaxLength);
|
||||
auto comb10MaxLength = static_cast<unsigned int>(C10 * roomMaxSize * sampleRate / 1000);
|
||||
comb10.resize(comb10MaxLength);
|
||||
auto comb11MaxLength = static_cast<unsigned int>(C11 * roomMaxSize * sampleRate / 1000);
|
||||
comb11.resize(comb11MaxLength);
|
||||
auto comb12MaxLength = static_cast<unsigned int>(C12 * roomMaxSize * sampleRate / 1000);
|
||||
comb12.resize(comb12MaxLength);
|
||||
|
||||
allpassL1Length = static_cast<unsigned int>(AL1 * sampleRate / 1000);
|
||||
allpassL1.resize(allpassL1Length);
|
||||
allpassL2Length = static_cast<unsigned int>((AL2 + SW) * sampleRate / 1000);
|
||||
allpassL2.resize(allpassL2Length);
|
||||
allpassL3Length = static_cast<unsigned int>(AL3 * sampleRate / 1000);
|
||||
allpassL3.resize(allpassL3Length);
|
||||
|
||||
allpassR1Length = static_cast<unsigned int>((AR1 + SW) * sampleRate / 1000);
|
||||
allpassR1.resize(allpassR1Length);
|
||||
allpassR2Length = static_cast<unsigned int>(AR2 * sampleRate / 1000);
|
||||
allpassR2.resize(allpassR2Length);
|
||||
allpassR3Length = static_cast<unsigned int>((AR3 + SW) * sampleRate / 1000);
|
||||
allpassR3.resize(allpassR3Length);
|
||||
|
||||
auto preDelayMaxLength = static_cast<unsigned int>(500 * sampleRate / 1000);
|
||||
preDelay.resize(preDelayMaxLength);
|
||||
|
||||
flushPreDelay();
|
||||
flushBuffers();
|
||||
|
||||
allpassL1Pos = allpassL2Pos = allpassL3Pos = allpassR1Pos = allpassR2Pos = allpassR3Pos = 0;
|
||||
tmp1LP = tmp2LP = tmp1HP = tmp2HP = 0;
|
||||
|
||||
comb1Pos = comb2Pos = comb3Pos = comb4Pos = comb5Pos = comb6Pos = comb7Pos = comb8Pos = 0;
|
||||
comb9Pos = comb10Pos = comb11Pos = comb12Pos = 0;
|
||||
preDelayPos = 0;
|
||||
}
|
||||
|
||||
void gin::SimpleVerb::flushPreDelay()
|
||||
{
|
||||
std::fill(preDelay.begin(), preDelay.end(), 0.0f);
|
||||
}
|
||||
|
||||
void gin::SimpleVerb::flushBuffers()
|
||||
{
|
||||
std::fill(comb1.begin(), comb1.end(), 0.0f);
|
||||
std::fill(comb2.begin(), comb2.end(), 0.0f);
|
||||
std::fill(comb3.begin(), comb3.end(), 0.0f);
|
||||
std::fill(comb4.begin(), comb4.end(), 0.0f);
|
||||
std::fill(comb5.begin(), comb5.end(), 0.0f);
|
||||
std::fill(comb6.begin(), comb6.end(), 0.0f);
|
||||
std::fill(comb7.begin(), comb7.end(), 0.0f);
|
||||
std::fill(comb8.begin(), comb8.end(), 0.0f);
|
||||
std::fill(comb9.begin(), comb9.end(), 0.0f);
|
||||
std::fill(comb10.begin(), comb10.end(), 0.0f);
|
||||
std::fill(comb11.begin(), comb11.end(), 0.0f);
|
||||
std::fill(comb12.begin(), comb12.end(), 0.0f);
|
||||
std::fill(allpassL1.begin(), allpassL1.end(), 0.0f);
|
||||
std::fill(allpassL2.begin(), allpassL2.end(), 0.0f);
|
||||
std::fill(allpassL3.begin(), allpassL3.end(), 0.0f);
|
||||
std::fill(allpassR1.begin(), allpassR1.end(), 0.0f);
|
||||
std::fill(allpassR2.begin(), allpassR2.end(), 0.0f);
|
||||
std::fill(allpassR3.begin(), allpassR3.end(), 0.0f);
|
||||
}
|
||||
|
||||
void gin::SimpleVerb::setParameters(float roomIn, float dampIn, float preDelayIn, float lpFaderIn, float hpFaderIn, float wetIn, float dryIn)
|
||||
{
|
||||
if (!juce::approximatelyEqual(roomIn, roomSizeFader))
|
||||
{
|
||||
roomSizeFader = roomIn;
|
||||
roomSize = 5 + roomSizeFader * roomSizeFader * 95;
|
||||
|
||||
comb1Length = static_cast<unsigned int>(C1 * roomSize * sampleRate / 1000);
|
||||
comb1Pos = 0;
|
||||
|
||||
comb2Length = static_cast<unsigned int>(C2 * roomSize * sampleRate / 1000);
|
||||
comb2Pos = 0;
|
||||
|
||||
comb3Length = static_cast<unsigned int>(C3 * roomSize * sampleRate / 1000);
|
||||
comb3Pos = 0;
|
||||
|
||||
comb4Length = static_cast<unsigned int>(C4 * roomSize * sampleRate / 1000);
|
||||
comb4Pos = 0;
|
||||
|
||||
comb5Length = static_cast<unsigned int>(C5 * roomSize * sampleRate / 1000);
|
||||
comb5Pos = 0;
|
||||
|
||||
comb6Length = static_cast<unsigned int>(C6 * roomSize * sampleRate / 1000);
|
||||
comb6Pos = 0;
|
||||
|
||||
comb7Length = static_cast<unsigned int>(C7 * roomSize * sampleRate / 1000);
|
||||
comb7Pos = 0;
|
||||
|
||||
comb8Length = static_cast<unsigned int>(C8 * roomSize * sampleRate / 1000);
|
||||
comb8Pos = 0;
|
||||
|
||||
comb9Length = static_cast<unsigned int>(C9 * roomSize * sampleRate / 1000);
|
||||
comb9Pos = 0;
|
||||
|
||||
comb10Length = static_cast<unsigned int>(C10 * roomSize * sampleRate / 1000);
|
||||
comb10Pos = 0;
|
||||
|
||||
comb11Length = static_cast<unsigned int>(C11 * roomSize * sampleRate / 1000);
|
||||
comb11Pos = 0;
|
||||
|
||||
comb12Length = static_cast<unsigned int>(C12 * roomSize * sampleRate / 1000);
|
||||
comb12Pos = 0;
|
||||
|
||||
flushBuffers();
|
||||
}
|
||||
if (!juce::approximatelyEqual(dampIn, dampFader))
|
||||
{
|
||||
dampFader = dampIn;
|
||||
damp = std::min(1.0f - dampFader * dampFader, 0.95f);
|
||||
}
|
||||
if (!juce::approximatelyEqual(preDelayIn, preDelayFader))
|
||||
{
|
||||
preDelayFader = preDelayIn;
|
||||
preDelayLength = static_cast<unsigned int>(preDelayFader * preDelayFader * 250 * sampleRate / 1000);
|
||||
preDelayPos = 0;
|
||||
flushPreDelay();
|
||||
}
|
||||
if (!juce::approximatelyEqual(lpFaderIn, freqLPFader))
|
||||
{
|
||||
freqLPFader = lpFaderIn;
|
||||
freqLP = freqLPFader * freqLPFader * freqLPFader * 24000;
|
||||
b1LP = -std::exp(-2.0f * juce::MathConstants<float>::pi * freqLP / sampleRate); // 100Hz
|
||||
a0LP = 1.0f + b1LP;
|
||||
}
|
||||
if (!juce::approximatelyEqual(hpFaderIn, freqHPFader))
|
||||
{
|
||||
freqHPFader = hpFaderIn;
|
||||
freqHP = freqHPFader * freqHPFader * freqHPFader * 24000;
|
||||
b1HP = -std::exp(-2.0f * juce::MathConstants<float>::pi * freqHP / sampleRate); // 100Hz
|
||||
a0HP = 1.0f + b1HP;
|
||||
}
|
||||
if (!juce::approximatelyEqual(dryIn, dryFader))
|
||||
{
|
||||
dryFader = dryIn;
|
||||
dry = dryFader * 2;
|
||||
}
|
||||
if (!juce::approximatelyEqual(wetIn, wetFader))
|
||||
{
|
||||
wetFader = wetIn;
|
||||
wet = wetFader * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void gin::SimpleVerb::process(const float* in1, const float* in2, float* out1, float* out2, int numSamples)
|
||||
{
|
||||
int sampleFrames = numSamples;
|
||||
|
||||
while (--sampleFrames >= 0)
|
||||
{
|
||||
if (preDelayLength <= 1)
|
||||
{
|
||||
reverb = ((*in1) + (*in2)) / (1 + damp) + cDC_;
|
||||
}
|
||||
else
|
||||
{
|
||||
preDelay[preDelayPos] = ((*in1) + (*in2)) / (1 + damp) + cDC_;
|
||||
if (++preDelayPos >= preDelayLength)
|
||||
preDelayPos = 0;
|
||||
|
||||
reverb = preDelay[preDelayPos];
|
||||
}
|
||||
|
||||
comb1[comb1Pos] = reverb * 0.49f + comb1[comb1Pos] * damp;
|
||||
comb2[comb2Pos] = reverb * 0.76f + comb2[comb2Pos] * damp;
|
||||
comb3[comb3Pos] = reverb * 1.00f + comb3[comb3Pos] * damp;
|
||||
comb4[comb4Pos] = reverb * 0.91f + comb4[comb4Pos] * damp;
|
||||
comb5[comb5Pos] = reverb * 0.79f + comb5[comb5Pos] * damp;
|
||||
comb6[comb6Pos] = reverb * 0.71f + comb6[comb6Pos] * damp;
|
||||
comb7[comb7Pos] = reverb * 0.59f + comb7[comb7Pos] * damp;
|
||||
comb8[comb8Pos] = reverb * 0.51f + comb8[comb8Pos] * damp;
|
||||
comb9[comb9Pos] = reverb * 0.42f + comb9[comb9Pos] * damp;
|
||||
comb10[comb10Pos] = reverb * 0.38f + comb10[comb10Pos] * damp;
|
||||
comb11[comb11Pos] = reverb * 0.35f + comb11[comb11Pos] * damp;
|
||||
comb12[comb12Pos] = reverb * 0.30f + comb12[comb12Pos] * damp;
|
||||
|
||||
if (++comb1Pos >= comb1Length) comb1Pos = 0;
|
||||
if (++comb2Pos >= comb2Length) comb2Pos = 0;
|
||||
if (++comb3Pos >= comb3Length) comb3Pos = 0;
|
||||
if (++comb4Pos >= comb4Length) comb4Pos = 0;
|
||||
if (++comb5Pos >= comb5Length) comb5Pos = 0;
|
||||
if (++comb6Pos >= comb6Length) comb6Pos = 0;
|
||||
if (++comb7Pos >= comb7Length) comb7Pos = 0;
|
||||
if (++comb8Pos >= comb8Length) comb8Pos = 0;
|
||||
if (++comb9Pos >= comb9Length) comb9Pos = 0;
|
||||
if (++comb10Pos >= comb10Length) comb10Pos = 0;
|
||||
if (++comb11Pos >= comb11Length) comb11Pos = 0;
|
||||
if (++comb12Pos >= comb12Length) comb12Pos = 0;
|
||||
|
||||
reverb = (comb1[comb1Pos]
|
||||
+ comb2[comb2Pos]
|
||||
+ comb3[comb3Pos]
|
||||
+ comb4[comb4Pos]
|
||||
+ comb5[comb5Pos]
|
||||
+ comb6[comb6Pos]
|
||||
+ comb7[comb7Pos]
|
||||
+ comb8[comb8Pos]
|
||||
+ comb9[comb9Pos]
|
||||
+ comb10[comb10Pos]
|
||||
+ comb11[comb11Pos]
|
||||
+ comb12[comb12Pos]);
|
||||
|
||||
jassert(!std::isnan(reverb) && !std::isinf(reverb));
|
||||
|
||||
allpassL1[allpassL1Pos] = reverb + allpassL1[allpassL1Pos] * AP1FBQ;
|
||||
left = (reverb - allpassL1[allpassL1Pos] * AP1FBQ);
|
||||
jassert(!std::isnan(left) && !std::isinf(left));
|
||||
if (++allpassL1Pos >= allpassL1Length)
|
||||
allpassL1Pos = 0;
|
||||
|
||||
allpassL2[allpassL2Pos] = left + allpassL2[allpassL2Pos] * AP2FBQ;
|
||||
left = (left - allpassL2[allpassL2Pos] * AP2FBQ);
|
||||
jassert(!std::isnan(left) && !std::isinf(left));
|
||||
if (++allpassL2Pos >= allpassL2Length)
|
||||
allpassL2Pos = 0;
|
||||
|
||||
allpassL3[allpassL3Pos] = left + allpassL3[allpassL3Pos] * AP3FBQ;
|
||||
left = (left - allpassL3[allpassL3Pos] * AP3FBQ);
|
||||
jassert(!std::isnan(left) && !std::isinf(left));
|
||||
if (++allpassL3Pos >= allpassL3Length)
|
||||
allpassL3Pos = 0;
|
||||
|
||||
allpassR1[allpassR1Pos] = reverb + allpassR1[allpassR1Pos] * AP1FBQ;
|
||||
right = (reverb - allpassR1[allpassR1Pos] * AP1FBQ);
|
||||
jassert(!std::isnan(right) && !std::isinf(right));
|
||||
if (++allpassR1Pos >= allpassR1Length)
|
||||
allpassR1Pos = 0;
|
||||
|
||||
allpassR2[allpassR2Pos] = right + allpassR2[allpassR2Pos] * AP2FBQ;
|
||||
right = (right - allpassR2[allpassR2Pos] * AP2FBQ);
|
||||
jassert(!std::isnan(right) && !std::isinf(right));
|
||||
if (++allpassR2Pos >= allpassR2Length)
|
||||
allpassR2Pos = 0;
|
||||
|
||||
allpassR3[allpassR3Pos] = right + allpassR3[allpassR3Pos] * AP3FBQ;
|
||||
right = (right - allpassR3[allpassR3Pos] * AP3FBQ);
|
||||
jassert(!std::isnan(right) && !std::isinf(right));
|
||||
if (++allpassR3Pos >= allpassR3Length)
|
||||
allpassR3Pos = 0;
|
||||
|
||||
if (!juce::approximatelyEqual(freqHPFader, 0.0f))
|
||||
{
|
||||
left -= (tmp1HP = a0HP * left - b1HP * tmp1HP + cDC_) - cDC_;
|
||||
right -= (tmp2HP = a0HP * right - b1HP * tmp2HP + cDC_) - cDC_;
|
||||
|
||||
jassert(!std::isnan(left) && !std::isinf(left));
|
||||
jassert(!std::isnan(right) && !std::isinf(right));
|
||||
}
|
||||
if (!juce::approximatelyEqual(freqLPFader, 1.0f))
|
||||
{
|
||||
left = (tmp1LP = a0LP * left - b1LP * tmp1LP + cDC_) - cDC_;
|
||||
right = (tmp2LP = a0LP * right - b1LP * tmp2LP + cDC_) - cDC_;
|
||||
|
||||
jassert(!std::isnan(left) && !std::isinf(left));
|
||||
jassert(!std::isnan(right) && !std::isinf(right));
|
||||
}
|
||||
|
||||
(*out1++) = (*in1++) * dry + left * wet;
|
||||
(*out2++) = (*in2++) * dry + right * wet;
|
||||
}
|
||||
}
|
||||
134
External/Gin/gin_simpleverb.h
vendored
Normal file
134
External/Gin/gin_simpleverb.h
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the GIN library.
|
||||
Copyright (c) 2019 - Roland Rabien.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
|
||||
namespace gin
|
||||
{
|
||||
|
||||
/** Simple Reverb
|
||||
|
||||
Copyright (c) 2006-2008 and 2012, Michael "LOSER" Gruhn
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
class SimpleVerb
|
||||
{
|
||||
public:
|
||||
SimpleVerb();
|
||||
|
||||
void setSampleRate(float sr);
|
||||
void process(const float* in1, const float* in2, float* out1, float* out2, int numSamples);
|
||||
void setParameters(float roomIn, float dampIn, float preDelayIn, float lpFaderIn, float hpFaderIn, float wetIn, float dryIn);
|
||||
|
||||
private:
|
||||
void flushPreDelay();
|
||||
void flushBuffers();
|
||||
|
||||
unsigned int preDelayPos, preDelayLength;
|
||||
|
||||
std::vector<float> preDelay;
|
||||
float preDelayFader;
|
||||
|
||||
unsigned int comb1Pos, comb1Length;
|
||||
std::vector<float> comb1;
|
||||
unsigned int comb2Pos, comb2Length;
|
||||
std::vector<float> comb2;
|
||||
unsigned int comb3Pos, comb3Length;
|
||||
std::vector<float> comb3;
|
||||
unsigned int comb4Pos, comb4Length;
|
||||
std::vector<float> comb4;
|
||||
unsigned int comb5Pos, comb5Length;
|
||||
std::vector<float> comb5;
|
||||
unsigned int comb6Pos, comb6Length;
|
||||
std::vector<float> comb6;
|
||||
unsigned int comb7Pos, comb7Length;
|
||||
std::vector<float> comb7;
|
||||
unsigned int comb8Pos, comb8Length;
|
||||
std::vector<float> comb8;
|
||||
unsigned int comb9Pos, comb9Length;
|
||||
std::vector<float> comb9;
|
||||
unsigned int comb10Pos, comb10Length;
|
||||
std::vector<float> comb10;
|
||||
unsigned int comb11Pos, comb11Length;
|
||||
std::vector<float> comb11;
|
||||
unsigned int comb12Pos, comb12Length;
|
||||
std::vector<float> comb12;
|
||||
|
||||
unsigned int allpassL1Pos, allpassL1Length;
|
||||
std::vector<float> allpassL1;
|
||||
unsigned int allpassL2Pos, allpassL2Length;
|
||||
std::vector<float> allpassL2;
|
||||
unsigned int allpassL3Pos, allpassL3Length;
|
||||
std::vector<float> allpassL3;
|
||||
|
||||
unsigned int allpassR1Pos, allpassR1Length;
|
||||
std::vector<float> allpassR1;
|
||||
unsigned int allpassR2Pos, allpassR2Length;
|
||||
std::vector<float> allpassR2;
|
||||
unsigned int allpassR3Pos, allpassR3Length;
|
||||
std::vector<float> allpassR3;
|
||||
|
||||
float reverb, damp, dry, wet, left, right;
|
||||
float roomSize = -1.0f;
|
||||
float roomSizeFader = -1.0f;
|
||||
float dampFader = -1.0f;
|
||||
float dryFader = -1.0f;
|
||||
float wetFader = -1.0f;
|
||||
float sampleRate = 44100.0f;
|
||||
|
||||
float freqLP, freqLPFader;
|
||||
float freqHP, freqHPFader;
|
||||
|
||||
float a0LP, b1LP, tmp1LP, tmp2LP;
|
||||
float a0HP, b1HP, tmp1HP, tmp2HP;
|
||||
|
||||
static constexpr float cDC_ = 1e-30f;
|
||||
|
||||
static constexpr float C1 = 1.00f;
|
||||
static constexpr float C2 = 1.09f;
|
||||
static constexpr float C3 = 1.16f;
|
||||
static constexpr float C4 = 1.23f;
|
||||
static constexpr float C5 = 1.32f;
|
||||
static constexpr float C6 = 1.41f;
|
||||
static constexpr float C7 = 1.45f;
|
||||
static constexpr float C8 = 1.56f;
|
||||
static constexpr float C9 = 1.66f;
|
||||
static constexpr float C10 = 1.71f;
|
||||
static constexpr float C11 = 1.80f;
|
||||
static constexpr float C12 = 1.90f;
|
||||
|
||||
static constexpr float AL1 = 1.0f;
|
||||
static constexpr float AL2 = 2.5f;
|
||||
static constexpr float AL3 = 5.0f;
|
||||
static constexpr float AR1 = 1.0f;
|
||||
static constexpr float AR2 = 2.5f;
|
||||
static constexpr float AR3 = 5.0f;
|
||||
|
||||
static constexpr float SW = 1.0f;
|
||||
|
||||
static constexpr float AP1FBQ = 0.6f;
|
||||
static constexpr float AP2FBQ = 0.6f;
|
||||
static constexpr float AP3FBQ = 0.6f;
|
||||
};
|
||||
} // namespace gin
|
||||
Loading…
Add table
Add a link
Reference in a new issue