/
SmoothSynth.ck
102 lines (76 loc) · 2.11 KB
/
SmoothSynth.ck
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include(Control)
class SmoothSynth extends ControlDispatcher
{
SinOsc bank;
ADSR envelope;
-1 => int lastPitch;
false => int isPlaying;
300 => int glideLengthInMs;
init();
fun void init()
{
// init oscilators
0 => bank.gain;
// init envelope
30::ms => envelope.attackTime;
// 3 => envelope.attackRate;
// 20::ms => envelope.decayTime;
// 1.0 => envelope.decayRate;
0.7 => envelope.sustainLevel;
160::ms => envelope.releaseTime;
// 1.0 => envelope.releaseRate;
// setup route
bank => envelope => dac;
}
fun void noteOn(int pitch, int velocity)
{
(Std.mtof(pitch) != bank.freq() && isPlaying) => int doGlide;
pitch => lastPitch;
true => isPlaying;
if(doGlide)
{
glide(pitch, velocity);
}
else
{
attack(pitch, velocity);
}
}
fun void noteOff(int pitch, int velocity)
{
if(pitch == lastPitch)
{
-1 => lastPitch;
// Give the system a little time to wait for another note on.
10::ms => now;
if(lastPitch == -1)
{
false => isPlaying;
envelope.keyOff();
}
}
}
fun void glide(int pitch, int velocity)
{
// <<< "glide" >>>;
bank.freq() => float oldFreq;
bank.gain() => float oldGain;
Std.mtof(pitch) => float newFreq;
velocity / 127.0 => float newGain;
for(1 => int i; i <= glideLengthInMs && pitch == lastPitch; i++)
{
(i $ float) / (glideLengthInMs $ float) => float coef;
Math.pow(coef, 3);
(1.0 - coef) * oldFreq + coef * newFreq => bank.freq;
(1.0 - coef) * oldGain + coef * newGain => bank.gain;
1::ms => now;
}
}
fun void attack(int pitch, int velocity)
{
// <<< "attack" >>>;
Std.mtof(pitch) => bank.freq;
velocity / 127.0 => bank.gain;
envelope.keyOn();
}
}