File hihat.h¶
File List > DaisySP > Source > Drums > hihat.h
Go to the documentation of this file
Source Code¶
/*
Copyright (c) 2020 Electrosmith, Corp, Emilie Gillet
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/
#pragma once
#ifndef DSY_HIHAT_H
#define DSY_HIHAT_H
#include "Filters/svf.h"
#include "Synthesis/oscillator.h"
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
namespace daisysp
{
class SquareNoise
{
public:
SquareNoise() {}
~SquareNoise() {}
void Init(float sample_rate);
float Process(float f0);
private:
uint32_t phase_[6];
};
class RingModNoise
{
public:
RingModNoise() {}
~RingModNoise() {}
void Init(float sample_rate);
float Process(float f0);
private:
float ProcessPair(Oscillator* osc, float f1, float f2);
Oscillator oscillator_[6];
float sample_rate_;
};
class SwingVCA
{
public:
float operator()(float s, float gain)
{
s *= s > 0.0f ? 10.0f : 0.1f;
s = s / (1.0f + fabsf(s));
return (s + 1.0f) * gain;
}
};
class LinearVCA
{
public:
float operator()(float s, float gain) { return s * gain; }
};
template <typename MetallicNoiseSource = SquareNoise,
typename VCA = LinearVCA,
bool resonance = true>
class HiHat
{
public:
HiHat() {}
~HiHat() {}
void Init(float sample_rate)
{
sample_rate_ = sample_rate;
trig_ = false;
envelope_ = 0.0f;
noise_clock_ = 0.0f;
noise_sample_ = 0.0f;
sustain_gain_ = 0.0f;
SetFreq(3000.f);
SetTone(.5f);
SetDecay(.2f);
SetNoisiness(.8f);
SetAccent(.8f);
SetSustain(false);
metallic_noise_.Init(sample_rate_);
noise_coloration_svf_.Init(sample_rate_);
hpf_.Init(sample_rate_);
}
float Process(bool trigger = false)
{
const float envelope_decay
= 1.0f - 0.003f * SemitonesToRatio(-decay_ * 84.0f);
const float cut_decay
= 1.0f - 0.0025f * SemitonesToRatio(-decay_ * 36.0f);
if(trigger || trig_)
{
trig_ = false;
envelope_
= (1.5f + 0.5f * (1.0f - decay_)) * (0.3f + 0.7f * accent_);
}
// Process the metallic noise.
float out = metallic_noise_.Process(2.0f * f0_);
// Apply BPF on the metallic noise.
float cutoff = 150.0f / sample_rate_ * SemitonesToRatio(tone_ * 72.0f);
cutoff = fclamp(cutoff, 0.0f, 16000.0f / sample_rate_);
noise_coloration_svf_.SetFreq(cutoff * sample_rate_);
noise_coloration_svf_.SetRes(resonance ? 3.0f + 6.0f * tone_ : 1.0f);
noise_coloration_svf_.Process(out);
out = noise_coloration_svf_.Band();
// This is not at all part of the 808 circuit! But to add more variety, we
// add a variable amount of clocked noise to the output of the 6 schmitt
// trigger oscillators.
float noise_f = f0_ * (16.0f + 16.0f * (1.0f - noisiness_));
noise_f = fclamp(noise_f, 0.0f, 0.5f);
noise_clock_ += noise_f;
if(noise_clock_ >= 1.0f)
{
noise_clock_ -= 1.0f;
noise_sample_ = rand() * kRandFrac - 0.5f;
}
out += noisiness_ * (noise_sample_ - out);
// Apply VCA.
sustain_gain_ = accent_ * decay_;
VCA vca;
envelope_ *= envelope_ > 0.5f ? envelope_decay : cut_decay;
out = vca(out, sustain_ ? sustain_gain_ : envelope_);
hpf_.SetFreq(cutoff * sample_rate_);
hpf_.SetRes(.5f);
hpf_.Process(out);
out = hpf_.High();
return out;
}
void Trig() { trig_ = true; }
void SetSustain(bool sustain) { sustain_ = sustain; }
void SetAccent(float accent) { accent_ = fclamp(accent, 0.f, 1.f); }
void SetFreq(float f0)
{
f0 /= sample_rate_;
f0_ = fclamp(f0, 0.f, 1.f);
}
void SetTone(float tone) { tone_ = fclamp(tone, 0.f, 1.f); }
void SetDecay(float decay)
{
decay_ = fmax(decay, 0.f);
decay_ *= 1.7;
decay_ -= 1.2;
}
void SetNoisiness(float noisiness)
{
noisiness_ = fclamp(noisiness, 0.f, 1.f);
noisiness_ *= noisiness_;
}
private:
float sample_rate_;
float accent_, f0_, tone_, decay_, noisiness_;
bool sustain_;
bool trig_;
float SemitonesToRatio(float in) { return powf(2.f, in * kOneTwelfth); }
float envelope_;
float noise_clock_;
float noise_sample_;
float sustain_gain_;
MetallicNoiseSource metallic_noise_;
Svf noise_coloration_svf_;
Svf hpf_;
};
} // namespace daisysp
#endif
#endif