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.
 
 

219 lines
5.3 KiB

#include "../utility/dsp.h"
#include "analogsnaredrum.h"
#include <math.h>
#include <stdlib.h>
using namespace daisysp;
static const int kNumModes = 5;
void AnalogSnareDrum::Init(float sample_rate)
{
sample_rate_ = sample_rate;
trig_ = false;
pulse_remaining_samples_ = 0;
pulse_ = 0.0f;
pulse_height_ = 0.0f;
pulse_lp_ = 0.0f;
noise_envelope_ = 0.0f;
sustain_gain_ = 0.0f;
SetSustain(false);
SetAccent(.6f);
SetFreq(200.f);
SetDecay(.3f);
SetSnappy(.7f);
SetTone(.5f);
for(int i = 0; i < kNumModes; ++i)
{
resonator_[i].Init(sample_rate_);
phase_[i] = 0.f;
}
noise_filter_.Init(sample_rate_);
}
/** Trigger the drum */
void AnalogSnareDrum::Trig()
{
trig_ = true;
}
void AnalogSnareDrum::SetSustain(bool sustain)
{
sustain_ = sustain;
}
void AnalogSnareDrum::SetAccent(float accent)
{
accent_ = fclamp(accent, 0.f, 1.f);
}
void AnalogSnareDrum::SetFreq(float f0)
{
f0 = f0 / sample_rate_;
f0_ = fclamp(f0, 0.f, .4f);
}
void AnalogSnareDrum::SetTone(float tone)
{
tone_ = fclamp(tone, 0.f, 1.f);
tone_ *= 2.f;
}
void AnalogSnareDrum::SetDecay(float decay)
{
decay_ = decay;
return;
decay_ = fmax(decay, 0.f);
}
void AnalogSnareDrum::SetSnappy(float snappy)
{
snappy_ = fclamp(snappy, 0.f, 1.f);
}
float AnalogSnareDrum::Process(bool trigger)
{
const float decay_xt = decay_ * (1.0f + decay_ * (decay_ - 1.0f));
const int kTriggerPulseDuration = 1.0e-3 * sample_rate_;
const float kPulseDecayTime = 0.1e-3 * sample_rate_;
const float q = 2000.0f * powf(2.f, kOneTwelfth * decay_xt * 84.0f);
const float noise_envelope_decay
= 1.0f
- 0.0017f
* powf(2.f,
kOneTwelfth * (-decay_ * (50.0f + snappy_ * 10.0f)));
const float exciter_leak = snappy_ * (2.0f - snappy_) * 0.1f;
float snappy = snappy_ * 1.1f - 0.05f;
snappy = fclamp(snappy, 0.0f, 1.0f);
float tone = tone_;
if(trigger || trig_)
{
trig_ = false;
pulse_remaining_samples_ = kTriggerPulseDuration;
pulse_height_ = 3.0f + 7.0f * accent_;
noise_envelope_ = 2.0f;
}
static const float kModeFrequencies[kNumModes]
= {1.00f, 2.00f, 3.18f, 4.16f, 5.62f};
float f[kNumModes];
float gain[kNumModes];
for(int i = 0; i < kNumModes; ++i)
{
f[i] = fmin(f0_ * kModeFrequencies[i], 0.499f);
resonator_[i].SetFreq(f[i] * sample_rate_);
// resonator_[i].SetRes(1.0f + f[i] * (i == 0 ? q : q * 0.25f));
resonator_[i].SetRes((f[i] * (i == 0 ? q : q * 0.25f)) * .2);
}
if(tone < 0.666667f)
{
// 808-style (2 modes)
tone *= 1.5f;
gain[0] = 1.5f + (1.0f - tone) * (1.0f - tone) * 4.5f;
gain[1] = 2.0f * tone + 0.15f;
for(int i = 2; i < kNumModes; i++)
{
gain[i] = 0.f;
}
}
else
{
// What the 808 could have been if there were extra modes!
tone = (tone - 0.666667f) * 3.0f;
gain[0] = 1.5f - tone * 0.5f;
gain[1] = 2.15f - tone * 0.7f;
for(int i = 2; i < kNumModes; ++i)
{
gain[i] = tone;
tone *= tone;
}
}
float f_noise = f0_ * 16.0f;
fclamp(f_noise, 0.0f, 0.499f);
noise_filter_.SetFreq(f_noise * sample_rate_);
//noise_filter_.SetRes(1.0f + f_noise * 1.5f);
noise_filter_.SetRes(f_noise * 1.5f);
// Q45 / Q46
float pulse = 0.0f;
if(pulse_remaining_samples_)
{
--pulse_remaining_samples_;
pulse = pulse_remaining_samples_ ? pulse_height_ : pulse_height_ - 1.0f;
pulse_ = pulse;
}
else
{
pulse_ *= 1.0f - 1.0f / kPulseDecayTime;
pulse = pulse_;
}
float sustain_gain_value = sustain_gain_ = accent_ * decay_;
// R189 / C57 / R190 + C58 / C59 / R197 / R196 / IC14
pulse_lp_ = fclamp(pulse_lp_, pulse, 0.75f);
float shell = 0.0f;
for(int i = 0; i < kNumModes; ++i)
{
float excitation
= i == 0 ? (pulse - pulse_lp_) + 0.006f * pulse : 0.026f * pulse;
phase_[i] += f[i];
phase_[i] = phase_[i] >= 1.f ? phase_[i] - 1.f : phase_[i];
resonator_[i].Process(excitation);
shell += gain[i]
* (sustain_
? sin(phase_[i] * TWOPI_F) * sustain_gain_value * 0.25f
: resonator_[i].Band() + excitation * exciter_leak);
}
shell = SoftClip(shell);
// C56 / R194 / Q48 / C54 / R188 / D54
float noise = 2.0f * rand() * kRandFrac - 1.0f;
if(noise < 0.0f)
noise = 0.0f;
noise_envelope_ *= noise_envelope_decay;
noise *= (sustain_ ? sustain_gain_value : noise_envelope_) * snappy * 2.0f;
// C66 / R201 / C67 / R202 / R203 / Q49
noise_filter_.Process(noise);
noise = noise_filter_.Band();
// IC13
return noise + shell * (1.0f - snappy);
}
inline float AnalogSnareDrum::SoftLimit(float x)
{
return x * (27.0f + x * x) / (27.0f + 9.0f * x * x);
}
inline float AnalogSnareDrum::SoftClip(float x)
{
if(x < -3.0f)
{
return -1.0f;
}
else if(x > 3.0f)
{
return 1.0f;
}
else
{
return SoftLimit(x);
}
}