forked from electro-smith/DaisySP
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* setup * building * sample based * default template * init sr * setters * fix setter bugs * init vals * tuned decay param * trig and comments * two consts * ratio and rand * stdlib
- Loading branch information
Showing
4 changed files
with
367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ fm2 \ | |
fold \ | ||
formantosc \ | ||
grainlet \ | ||
hihat \ | ||
jitter \ | ||
line \ | ||
limiter \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include "dsp.h" | ||
#include "hihat.h" | ||
#include <math.h> | ||
|
||
using namespace daisysp; | ||
|
||
void SquareNoise::Init(float sample_rate) | ||
{ | ||
for(int i = 0; i < 6; i++) | ||
{ | ||
phase_[i] = 0; | ||
} | ||
} | ||
|
||
float SquareNoise::Process(float f0) | ||
{ | ||
const float ratios[6] = {// Nominal f0: 414 Hz | ||
1.0f, | ||
1.304f, | ||
1.466f, | ||
1.787f, | ||
1.932f, | ||
2.536f}; | ||
|
||
uint32_t increment[6]; | ||
uint32_t phase[6]; | ||
for(int i = 0; i < 6; ++i) | ||
{ | ||
float f = f0 * ratios[i]; | ||
if(f >= 0.499f) | ||
f = 0.499f; | ||
increment[i] = static_cast<uint32_t>(f * 4294967296.0f); | ||
phase[i] = phase_[i]; | ||
} | ||
|
||
phase[0] += increment[0]; | ||
phase[1] += increment[1]; | ||
phase[2] += increment[2]; | ||
phase[3] += increment[3]; | ||
phase[4] += increment[4]; | ||
phase[5] += increment[5]; | ||
uint32_t noise = 0; | ||
noise += (phase[0] >> 31); | ||
noise += (phase[1] >> 31); | ||
noise += (phase[2] >> 31); | ||
noise += (phase[3] >> 31); | ||
noise += (phase[4] >> 31); | ||
noise += (phase[5] >> 31); | ||
|
||
for(int i = 0; i < 6; ++i) | ||
{ | ||
phase_[i] = phase[i]; | ||
} | ||
|
||
return 0.33f * static_cast<float>(noise) - 1.0f; | ||
} | ||
|
||
void RingModNoise::Init(float sample_rate) | ||
{ | ||
sample_rate_ = sample_rate; | ||
|
||
for(int i = 0; i < 6; ++i) | ||
{ | ||
oscillator_[i].Init(sample_rate_); | ||
} | ||
} | ||
|
||
float RingModNoise::Process(float f0) | ||
{ | ||
const float ratio = f0 / (0.01f + f0); | ||
const float f1a = 200.0f / sample_rate_ * ratio; | ||
const float f1b = 7530.0f / sample_rate_ * ratio; | ||
const float f2a = 510.0f / sample_rate_ * ratio; | ||
const float f2b = 8075.0f / sample_rate_ * ratio; | ||
const float f3a = 730.0f / sample_rate_ * ratio; | ||
const float f3b = 10500.0f / sample_rate_ * ratio; | ||
|
||
float out = ProcessPair(&oscillator_[0], f1a, f1b); | ||
out += ProcessPair(&oscillator_[2], f2a, f2b); | ||
out += ProcessPair(&oscillator_[4], f3a, f3b); | ||
|
||
return out; | ||
} | ||
|
||
float RingModNoise::ProcessPair(Oscillator* osc, float f1, float f2) | ||
{ | ||
osc[0].SetWaveform(Oscillator::WAVE_SQUARE); | ||
osc[0].SetFreq(f1 * sample_rate_); | ||
float temp_1 = osc[0].Process(); | ||
|
||
osc[1].SetWaveform(Oscillator::WAVE_SAW); | ||
osc[1].SetFreq(f2 * sample_rate_); | ||
float temp_2 = osc[1].Process(); | ||
|
||
return temp_1 * temp_2; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
#pragma once | ||
#ifndef DSY_HIHAT_H | ||
#define DSY_HIHAT_H | ||
|
||
#include "modules/svf.h" | ||
#include "modules/oscillator.h" | ||
|
||
#include <stdint.h> | ||
#include <stdlib.h> | ||
#ifdef __cplusplus | ||
|
||
/** @file hihat.h */ | ||
|
||
namespace daisysp | ||
{ | ||
/** | ||
@brief 808 style "metallic noise" with 6 square oscillators. | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
Ported from pichenettes/eurorack/plaits/dsp/drums/hihat.h \n | ||
to an independent module. \n | ||
Original code written by Emilie Gillet in 2016. \n | ||
*/ | ||
class SquareNoise | ||
{ | ||
public: | ||
SquareNoise() {} | ||
~SquareNoise() {} | ||
|
||
void Init(float sample_rate); | ||
|
||
float Process(float f0); | ||
|
||
private: | ||
uint32_t phase_[6]; | ||
}; | ||
|
||
/** | ||
@brief Ring mod style metallic noise generator. | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
Ported from pichenettes/eurorack/plaits/dsp/drums/hihat.h \n | ||
to an independent module. \n | ||
Original code written by Emilie Gillet in 2016. \n | ||
*/ | ||
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_; | ||
}; | ||
|
||
/** | ||
@brief Swing type VCA | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
Ported from pichenettes/eurorack/plaits/dsp/drums/hihat.h \n | ||
to an independent module. \n | ||
Original code written by Emilie Gillet in 2016. \n | ||
*/ | ||
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; | ||
} | ||
}; | ||
|
||
/** | ||
@brief Linear type VCA | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
Ported from pichenettes/eurorack/plaits/dsp/drums/hihat.h \n | ||
to an independent module. \n | ||
Original code written by Emilie Gillet in 2016. \n | ||
*/ | ||
class LinearVCA | ||
{ | ||
public: | ||
float operator()(float s, float gain) { return s * gain; } | ||
}; | ||
|
||
/** | ||
@brief 808 HH, with a few extra parameters to push things to the CY territory... | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
The template parameter MetallicNoiseSource allows another kind of "metallic \n | ||
noise" to be used, for results which are more similar to KR-55 or FM hi-hats. \n \n | ||
Ported from pichenettes/eurorack/plaits/dsp/drums/hihat.h \n | ||
to an independent module. \n | ||
Original code written by Emilie Gillet in 2016. \n | ||
*/ | ||
template <typename MetallicNoiseSource = SquareNoise, | ||
typename VCA = LinearVCA, | ||
bool resonance = true> | ||
class HiHat | ||
{ | ||
public: | ||
HiHat() {} | ||
~HiHat() {} | ||
|
||
/** Initialize the module | ||
\param sample_rate Audio engine sample rate | ||
*/ | ||
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_); | ||
} | ||
|
||
/** Get the next sample | ||
\param trigger Hit the hihat with true. Defaults to false. | ||
*/ | ||
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; | ||
} | ||
|
||
/** Trigger the hihat */ | ||
void Trig() { trig_ = true; } | ||
|
||
/** Make the hihat ring out infinitely. | ||
\param sustain True = infinite sustain. | ||
*/ | ||
void SetSustain(bool sustain) { sustain_ = sustain; } | ||
|
||
/** Set how much accent to use | ||
\param accent Works 0-1. | ||
*/ | ||
void SetAccent(float accent) { accent_ = fclamp(accent, 0.f, 1.f); } | ||
|
||
/** Set the hihat tone's root frequency | ||
\param f0 Freq in Hz | ||
*/ | ||
void SetFreq(float f0) | ||
{ | ||
f0 /= sample_rate_; | ||
f0_ = fclamp(f0, 0.f, 1.f); | ||
} | ||
|
||
/** Set the overall brightness / darkness of the hihat. | ||
\param tone Works from 0-1. | ||
*/ | ||
void SetTone(float tone) { tone_ = fclamp(tone, 0.f, 1.f); } | ||
|
||
/** Set the length of the hihat decay | ||
\param decay Works > 0. Tuned for 0-1. | ||
*/ | ||
void SetDecay(float decay) | ||
{ | ||
decay_ = fmax(decay, 0.f); | ||
decay_ *= 1.7; | ||
decay_ -= 1.2; | ||
} | ||
|
||
/** Sets the mix between tone and noise | ||
\param snappy 1 = just noise. 0 = just tone. | ||
*/ | ||
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 |