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.

159 lines
3.6 KiB

4 years ago
#include "resonator.h"
#include <math.h>
using namespace daisysp;
void Resonator::Init(float position, int resolution, float sample_rate)
{
sample_rate_ = sample_rate;
SetFreq(440.f);
SetStructure(.5f);
SetBrightness(.5f);
SetDamping(.5f);
resolution_ = fmin(resolution, kMaxNumModes);
for(int i = 0; i < resolution; ++i)
{
mode_amplitude_[i] = cos(position * TWOPI_F) * 0.25f;
}
for(int i = 0; i < kMaxNumModes / kModeBatchSize; ++i)
{
mode_filters_[i].Init();
}
}
inline float NthHarmonicCompensation(int n, float stiffness)
{
float stretch_factor = 1.0f;
for(int i = 0; i < n - 1; ++i)
{
stretch_factor += stiffness;
if(stiffness < 0.0f)
{
stiffness *= 0.93f;
}
else
{
stiffness *= 0.98f;
}
}
return 1.0f / stretch_factor;
}
float Resonator::Process(const float in)
{
//convert Hz to cycles / sample
float out = 0.f;
float stiffness = CalcStiff(structure_);
float f0 = frequency_ * NthHarmonicCompensation(3, stiffness);
float brightness = brightness_;
float harmonic = f0;
float stretch_factor = 1.0f;
float input = damping_ * 79.7f;
float q_sqrt = powf(2.f, input * ratiofrac_);
float q = 500.0f * q_sqrt * q_sqrt;
brightness *= 1.0f - structure_ * 0.3f;
brightness *= 1.0f - damping_ * 0.3f;
float q_loss = brightness * (2.0f - brightness) * 0.85f + 0.15f;
float mode_q[kModeBatchSize];
float mode_f[kModeBatchSize];
float mode_a[kModeBatchSize];
int batch_counter = 0;
ResonatorSvf<kModeBatchSize>* batch_processor = &mode_filters_[0];
for(int i = 0; i < resolution_; ++i)
{
float mode_frequency = harmonic * stretch_factor;
if(mode_frequency >= 0.499f)
{
mode_frequency = 0.499f;
}
const float mode_attenuation = 1.0f - mode_frequency * 2.0f;
mode_f[batch_counter] = mode_frequency;
mode_q[batch_counter] = 1.0f + mode_frequency * q;
mode_a[batch_counter] = mode_amplitude_[i] * mode_attenuation;
++batch_counter;
if(batch_counter == kModeBatchSize)
{
batch_counter = 0;
batch_processor
->Process<ResonatorSvf<kModeBatchSize>::BAND_PASS, true>(
mode_f, mode_q, mode_a, in, &out);
++batch_processor;
}
stretch_factor += stiffness;
if(stiffness < 0.0f)
{
// Make sure that the partials do not fold back into negative frequencies.
stiffness *= 0.93f;
}
else
{
// This helps adding a few extra partials in the highest frequencies.
stiffness *= 0.98f;
}
harmonic += f0;
q *= q_loss;
}
return out;
}
void Resonator::SetFreq(float freq)
{
frequency_ = freq / sample_rate_;
}
void Resonator::SetStructure(float structure)
{
structure_ = fmax(fmin(structure, 1.f), 0.f);
}
void Resonator::SetBrightness(float brightness)
{
brightness_ = fmax(fmin(brightness, 1.f), 0.f);
}
void Resonator::SetDamping(float damping)
{
damping_ = fmax(fmin(damping, 1.f), 0.f);
}
float Resonator::CalcStiff(float sig)
{
if(sig < .25f)
{
sig = .25 - sig;
sig = -sig * .25;
}
else if(sig < .3f)
{
sig = 0.f;
}
else if(sig < .9f)
{
sig -= .3f;
sig *= stiff_frac_2;
}
else
{
sig -= .9f;
sig *= 10; // div by .1
sig *= sig;
sig = 1.5 - cos(sig * PI_F) * .5f;
}
return sig;
}