DaisySP
Loading...
Searching...
No Matches
hihat.h
Go to the documentation of this file.
1/*
2Copyright (c) 2020 Electrosmith, Corp, Emilie Gillet
3
4Use of this source code is governed by an MIT-style
5license that can be found in the LICENSE file or at
6https://opensource.org/licenses/MIT.
7*/
8
9#pragma once
10#ifndef DSY_HIHAT_H
11#define DSY_HIHAT_H
12
13#include "Filters/svf.h"
14#include "Synthesis/oscillator.h"
15
16#include <stdint.h>
17#include <stdlib.h>
18#ifdef __cplusplus
19
22namespace daisysp
23{
33{
34 public:
35 SquareNoise() {}
36 ~SquareNoise() {}
37
38 void Init(float sample_rate);
39
40 float Process(float f0);
41
42 private:
43 uint32_t phase_[6];
44};
45
55{
56 public:
57 RingModNoise() {}
58 ~RingModNoise() {}
59
60 void Init(float sample_rate);
61
62 float Process(float f0);
63
64 private:
65 float ProcessPair(Oscillator* osc, float f1, float f2);
66 Oscillator oscillator_[6];
67
68 float sample_rate_;
69};
70
80{
81 public:
82 float operator()(float s, float gain)
83 {
84 s *= s > 0.0f ? 10.0f : 0.1f;
85 s = s / (1.0f + fabsf(s));
86 return (s + 1.0f) * gain;
87 }
88};
89
99{
100 public:
101 float operator()(float s, float gain) { return s * gain; }
102};
103
114template <typename MetallicNoiseSource = SquareNoise,
115 typename VCA = LinearVCA,
116 bool resonance = true>
117class HiHat
118{
119 public:
120 HiHat() {}
121 ~HiHat() {}
122
126 void Init(float sample_rate)
127 {
128 sample_rate_ = sample_rate;
129
130 trig_ = false;
131
132 envelope_ = 0.0f;
133 noise_clock_ = 0.0f;
134 noise_sample_ = 0.0f;
135 sustain_gain_ = 0.0f;
136
137 SetFreq(3000.f);
138 SetTone(.5f);
139 SetDecay(.2f);
140 SetNoisiness(.8f);
141 SetAccent(.8f);
142 SetSustain(false);
143
144 metallic_noise_.Init(sample_rate_);
145 noise_coloration_svf_.Init(sample_rate_);
146 hpf_.Init(sample_rate_);
147 }
148
152 float Process(bool trigger = false)
153 {
154 const float envelope_decay
155 = 1.0f - 0.003f * SemitonesToRatio(-decay_ * 84.0f);
156 const float cut_decay
157 = 1.0f - 0.0025f * SemitonesToRatio(-decay_ * 36.0f);
158
159 if(trigger || trig_)
160 {
161 trig_ = false;
162
163 envelope_
164 = (1.5f + 0.5f * (1.0f - decay_)) * (0.3f + 0.7f * accent_);
165 }
166
167 // Process the metallic noise.
168 float out = metallic_noise_.Process(2.0f * f0_);
169
170 // Apply BPF on the metallic noise.
171 float cutoff = 150.0f / sample_rate_ * SemitonesToRatio(tone_ * 72.0f);
172
173 cutoff = fclamp(cutoff, 0.0f, 16000.0f / sample_rate_);
174
175
176 noise_coloration_svf_.SetFreq(cutoff * sample_rate_);
177 noise_coloration_svf_.SetRes(resonance ? 3.0f + 6.0f * tone_ : 1.0f);
178
179 noise_coloration_svf_.Process(out);
180 out = noise_coloration_svf_.Band();
181
182 // This is not at all part of the 808 circuit! But to add more variety, we
183 // add a variable amount of clocked noise to the output of the 6 schmitt
184 // trigger oscillators.
185 float noise_f = f0_ * (16.0f + 16.0f * (1.0f - noisiness_));
186 noise_f = fclamp(noise_f, 0.0f, 0.5f);
187
188 noise_clock_ += noise_f;
189 if(noise_clock_ >= 1.0f)
190 {
191 noise_clock_ -= 1.0f;
192 noise_sample_ = rand() * kRandFrac - 0.5f;
193 }
194 out += noisiness_ * (noise_sample_ - out);
195
196 // Apply VCA.
197 sustain_gain_ = accent_ * decay_;
198 VCA vca;
199 envelope_ *= envelope_ > 0.5f ? envelope_decay : cut_decay;
200 out = vca(out, sustain_ ? sustain_gain_ : envelope_);
201
202 hpf_.SetFreq(cutoff * sample_rate_);
203 hpf_.SetRes(.5f);
204 hpf_.Process(out);
205 out = hpf_.High();
206
207 return out;
208 }
209
211 void Trig() { trig_ = true; }
212
216 void SetSustain(bool sustain) { sustain_ = sustain; }
217
221 void SetAccent(float accent) { accent_ = fclamp(accent, 0.f, 1.f); }
222
226 void SetFreq(float f0)
227 {
228 f0 /= sample_rate_;
229 f0_ = fclamp(f0, 0.f, 1.f);
230 }
231
235 void SetTone(float tone) { tone_ = fclamp(tone, 0.f, 1.f); }
236
240 void SetDecay(float decay)
241 {
242 decay_ = fmax(decay, 0.f);
243 decay_ *= 1.7;
244 decay_ -= 1.2;
245 }
246
250 void SetNoisiness(float noisiness)
251 {
252 noisiness_ = fclamp(noisiness, 0.f, 1.f);
253 noisiness_ *= noisiness_;
254 }
255
256
257 private:
258 float sample_rate_;
259
260 float accent_, f0_, tone_, decay_, noisiness_;
261 bool sustain_;
262 bool trig_;
263
264 float SemitonesToRatio(float in) { return powf(2.f, in * kOneTwelfth); }
265
266 float envelope_;
267 float noise_clock_;
268 float noise_sample_;
269 float sustain_gain_;
270
271 MetallicNoiseSource metallic_noise_;
272 Svf noise_coloration_svf_;
273 Svf hpf_;
274};
275} // namespace daisysp
276#endif
277#endif
808 HH, with a few extra parameters to push things to the CY territory...
Definition hihat.h:118
void SetAccent(float accent)
Definition hihat.h:221
float Process(bool trigger=false)
Definition hihat.h:152
void SetNoisiness(float noisiness)
Definition hihat.h:250
void SetTone(float tone)
Definition hihat.h:235
void SetSustain(bool sustain)
Definition hihat.h:216
void SetDecay(float decay)
Definition hihat.h:240
void Init(float sample_rate)
Definition hihat.h:126
void Trig()
Definition hihat.h:211
void SetFreq(float f0)
Definition hihat.h:226
Linear type VCA.
Definition hihat.h:99
Definition oscillator.h:21
Ring mod style metallic noise generator.
Definition hihat.h:55
808 style "metallic noise" with 6 square oscillators.
Definition hihat.h:33
float Band()
Definition svf.h:68
void Process(float in)
Definition svf.cpp:31
void SetRes(float r)
Definition svf.cpp:71
void Init(float sample_rate)
Definition svf.cpp:8
float High()
Definition svf.h:64
void SetFreq(float f)
Definition svf.cpp:58
Swing type VCA.
Definition hihat.h:80
FIR Filter implementation, generic and ARM CMSIS DSP based.
Definition adenv.h:16
float fclamp(float in, float min, float max)
Definition dsp.h:64
float fmax(float a, float b)
Definition dsp.h:40