-
Notifications
You must be signed in to change notification settings - Fork 5
/
flutelib.dsp
118 lines (75 loc) · 2.86 KB
/
flutelib.dsp
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// WaveGuide Flute
import("math.lib");
import("effect.lib");
import("music.lib");
import("instrument.lib");
import("utils.dsp");
// parameters
pitch = hslider("pitch", 64, 32, 100, 1);
gain = nentry("gain", 1, 0, 1, 0.01);
gate = button("gate");
pitchBend = hslider("pitchBend", 0, -1, 1, 0.01);
_breathControl = nentry("breathControl", 0, 0, 1, 0.01);
// derived
smoothGate = max(gate, gate : smooth(0.999));
breathControl = _breathControl : smooth(breathControlSmoothing);
freq = midikey2hz(pitch : max(minPitch) : min(maxPitch));
// ALGORITHM IMPLEMENTATION
vibrato = env * osc(vibratoFreq)
with {
env = envVibrato(vibratoBegin, vibratoAttack, 100, vibratoRelease, gate);
};
//Breath pressure is controlled by an Attack / Decay / Sustain / Release envelope
envelopeBreath = pressure * adsr(envAttack, envDecay, 80, envRelease, gate)
with {
// keyboard scaling for attack, decay and release
// positive values : longer times for higher notes
// negative values : shorter times for higher notes
// zero: no scaling
envScaling = (pitch - 60) * envelopeScaling * 0.01;
// attack
envAttack = (pressure * envelopeAttack) + envScaling;
// decay
envDecay = envelopeDecay + envScaling;
// release
envRelease = envelopeRelease + envScaling;
};
jetDelay = fdelay(4096, SR / freq * jetRatio);
upperDelay = fdelay(4096, SR / freq * 0.5);
lowerDelay = fdelay(4096, (SR / freq * 0.5) - 1.0);
// FIXME
reflectionFilter = lowpass(1, reflectionFilterCutoff);
//reflectionFilter(x) = 0.5 * x + 0.5 * x';
// FIXME
boundaryLossFilter = lowpass(1, boundaryLossFilterCutoff);
//boundaryLossFilter(x) = 0.9 * x + 0.1 * x';
envelope = envelopeBreath + envelopeBreath * (vibratoGain * vibrato);
// jet nonlinearity
jetNonlinearity = sigmOut * tanh(sigmOffset + sigmIn * _);
// jetNonlinearity = sigmout * tanh(ampl * sigmoffset - signmin * _)
// references : [1]
// flute model
// references : [0], [1]
flute = ( (excitation : jet <:
// bore
(_, ((_,_ : _+_ : upperBore <: reflection,_ <: lowerBore,_,_,!)
// bore feedback
~ (feedbackGain * _)) ))
// jet feedback
~ (_,_ : directFeedbackGain * _ + _)) :
// out
!,!,_,_ : _ + _
with {
// TODO : improve
excitation = voicedGain * _ + (noiseGain * noise) : (envelope * _);
jet = jetDelay : jetNonlinearity : dcblocker;
upperBore = boundaryLossFilter : upperDelay;
lowerBore = lowerDelay;
reflection = reflectionGain * _ : reflectionFilter;
};
// [0] Waveguide simulation of neolithic chinese flutes (2001)
// Patricio de la Cuadra, Tamara Smyth, Chris Chafe, Han Baoqiang
// [1] An Improved Digital Waveguide model of a Flute - Implementation issues (1996)
// Vesa Välimäki, Rami Hänninen, Matti Karjalainen
// [2] On the Oscillations of Musical Instruments (1983)
// [3] A real-time DSP implementation of a flute model (1992)