Erosion and dilasion by square successfully tested.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / oscillator.lib
1 declare name "Faust Oscillator Library";
2 declare author "Julius O. Smith (jos at ccrma.stanford.edu)";
3 declare copyright "Julius O. Smith III";
4 declare version "1.10";
5 declare license "STK-4.3"; // Synthesis Tool Kit 4.3 (MIT style license)
6
7 import("music.lib"); // SR, ...
8 import("filter.lib"); // wgr, nlf2, tf2
9
10 //===================== Virtual Analog Oscillators ========================
11
12 //------------------------ Impulse Train: imptrain ------------------------
13 imptrain(freq) = sawpos(freq)<:-(mem)<0;
14
15 //--- Pulse-Train and Square-Wave Oscillators: pulsetrainpos, squarewave[pos]
16 // In all cases, the first pulse jumps to 1 at time 0.
17
18 // Basic unit-amplitude nonnegative pulse train with duty cycle between 0 and 1:
19 pulsetrainpos(freq,duty) = float(sawpos(freq) <= duty);
20
21 // Positive square wave = pulse train with 50% duty cycle:
22 squarewavepos(freq) = pulsetrainpos(freq,0.5);
23
24 // Unit amplitude square wave = zero-mean pulse train with 50% duty cycle:
25 squarewave(freq) = 2*squarewavepos(freq) - 1;
26
27 //---------- Sawtooth: rawsaw, sawpos, saw1, saw2, sawtooth -------------
28
29 // Sawtooth waveform oscillators for virtual analog synthesis et al.
30 // The 'simple' versions (rawsaw, sawpos, saw1), are mere samplings of
31 // the ideal continuous-time ("analog") waveforms. While simple, the
32 // aliasing due to sampling is quite audible. The differentiated
33 // polynomial waveform family (saw2,
34
35 // --- rawsaw ---
36 // simple sawtooth waveform oscillator between 0 and period in samples:
37 rawsaw(periodsamps) = (_,periodsamps : fmod) ~ +(1.0);
38
39 // --- sawpos ---
40 // simple sawtooth waveform oscillator between 0 and 1
41 sawpos(freq) = rawsaw(periodsamps) / periodsamps
42 with {
43 periodsamps = float(SR)/freq; // period in samples (not nec. integer)
44 };
45
46 // --- saw1 ---
47 // simple sawtooth waveform oscillator between -1 and 1
48 saw1(freq) = 2.0 * sawpos(freq) - 1.0; // zero-mean in [-1,1)
49
50 // --- saw2 ---
51 // Differentiated Parabolic Wave sawtooth (less aliasing)
52 // Reference: Valimaki, IEEE Signal Processing Letters, March 2005
53 saw2(freq) = saw1(freq) <: * <: -(mem) : *(0.25'*SR/freq);
54
55 // --- sawtooth ---
56 sawtooth = saw2; // default choice
57
58 //-------------------------- sawtooth_demo ---------------------------
59 // USAGE: sawtooth_demo : _
60
61 sawtooth_demo = signal with {
62 osc_group(x) = vgroup("[0] SAWTOOTH OSCILLATOR
63 [tooltip: See Faust's oscillator.lib for documentation and references]",x);
64 knob_group(x) = osc_group(hgroup("[1]", x));
65 ampdb = knob_group(vslider("[1] Amplitude [unit:dB] [style:knob]
66 [tooltip: Sawtooth waveform amplitude]",
67 -20,-120,10,0.1));
68 amp = ampdb : smooth(0.999) : db2linear;
69 freq = knob_group(
70 vslider("[2] Frequency [unit:PK] [style:knob]
71 [tooltip: Sawtooth frequency as a Piano Key (PK) number (A440 = key 49)]",
72 49,1,88,0.01) : pianokey2hz);
73 pianokey2hz(x) = 440.0*pow(2.0, (x-49.0)/12); // piano key 49 = A440 (also defined in effect.lib)
74 detune1 = 1 + 0.01 * knob_group(
75 vslider("[3] Detuning 1 [unit:%%] [style:knob]
76 [tooltip: Percentange frequency-shift up or down for second oscillator]",
77 -0.1,-10,10,0.01));
78 detune2 = 1 + 0.01 * knob_group(
79 vslider("[4] Detuning 2 [unit:%%] [style:knob]
80 [tooltip: Percentange frequency-shift up or down for third detuned oscillator]",
81 +0.1,-10,10,0.01));
82 portamento = knob_group(
83 vslider("[5] Portamento [unit:sec] [style:knob]
84 [tooltip: Portamento (frequency-glide) time-constant in seconds]",
85 0.1,0.01,1,0.001));
86 sfreq = freq : smooth(tau2pole(portamento));
87 tone = (amp/3) *
88 (sawtooth(sfreq) + sawtooth(sfreq*detune1) + sawtooth(sfreq*detune2));
89 signal = amp * select2(ei, select2(ss, tone, pink_noise), _);
90 checkbox_group(x) = knob_group(vgroup("[6] Alternate Signals",x));
91 ss = checkbox_group(checkbox("[0]
92 [tooltip: Pink Noise (or 1/f noise) is Constant-Q Noise, meaning that it has the same total power in every octave] Pink Noise Instead (uses only Amplitude control on the left)"));
93 ei = checkbox_group(checkbox(
94 "[1] External Input Instead (overrides Sawtooth/Noise selection above)"));
95 };
96
97 // --- Correction-filtered versions of saw2: saw2f2, saw2f4 ----
98 saw2f2 = saw2 : cf2 with {
99 cf2 = tf2(1.155704605878911, 0.745184288225518,0.040305967265900,
100 0.823765146386639, 0.117420665547108);
101 };
102
103 saw2f4 = saw2 : cf4 with {
104 cf4 = iir((1.155727435125014, 2.285861038554662,
105 1.430915027294021, 0.290713280893317, 0.008306401748854),
106 (2.156834679164532, 1.559532244409321, 0.423036498118354,
107 0.032080681130972));
108 };
109
110 // --- sawN, saw3,saw4,saw5,saw6 ---
111 // Differentiated Polynomial Wave (DPW) sawtooth (progressively less aliasing)
112 // Reference:
113 // "Alias-Suppressed Oscillators based on Differentiated Polynomial Waveforms",
114 // Vesa Valimaki, Juhan Nam, Julius Smith, and Jonathan Abel,
115 // IEEE Tr. Acoustics, Speech, and Language Processing (IEEE-ASLP),
116 // Vol. 18, no. 5, May 2010.
117
118 sawN(N,freq) = saw1 : poly(N) : D(N-1) : gate(N-1)
119 with {
120 p0n = SR/freq;
121 sawpos = (_,1:fmod) ~ +(1/p0n); // sawtooth waveform in [0,1)
122 saw1 = 2*sawpos - 1; // zero average mean, unit max amp
123 poly(2,x) = x*x;
124 poly(3,x) = x*x*x - x;
125 poly(4,x) = poly(2,x)*(poly(2,x) - 2);
126 poly(5,x) = pow(x,5) - pow(x,3)*10/3 + x*7/3;
127 poly(6,x) = pow(x,6) - 5*pow(x,4) + 7*poly(2,x);
128 diff1(x) = (x - x')/(2/p0n);
129 diff(N) = seq(n,N,diff1); // N diffs in series
130 D(1) = diff1/2;
131 D(2) = diff(2)/6;
132 D(3) = diff(3)/24;
133 D(4) = diff(4)/120;
134 D(5) = diff(5)/720;
135 gatedelay(n,d,x) = x@(int(d)&(n-1)); // from music.lib
136 gate(N) = * (1 : gatedelay(8,N)); // delayed step for blanking startup glitch
137 };
138 saw3 = sawN(3); saw4 = sawN(4); saw5 = sawN(5); saw6 = sawN(6);
139
140 //----------------------- Filter-Based Oscillators ------------------------
141
142 // Quick Guide (more complete documentation forthcoming):
143 //
144 // USAGE: osc[b|r|rs|rc|s|w](f), where f = frequency in Hz.
145 //
146 // oscb: one-multiply, two-adds, amplitude varies with frequency, avoid dc
147 // oscr: four-multipies, two-adds, amplitude unchanging with frequency,
148 // dc ok, amp slowly drifts,
149 // sine and cosine outputs available (exact phase quadrature)
150 // oscrs: sine output of oscr
151 // oscrc: cosine output of oscr
152 // oscs: two-multiplies, two-adds, amplitude varies slightly with frequency,
153 // dc ok, no amp drift, likely optimizable to be the fastest no-drift case
154 // oscw: one/two-multiply, three-adds, amplitude steady with frequency, no amp drift,
155 // sine and cosine outputs available (exact phase quadrature),
156 // numerical difficulty below 10 Hz,
157 // likely optimizable to be best (above 10 Hz) for custom silicon
158 // (one multiply when frequency is constant, two otherwise).
159
160 impulse = 1-1'; // used to start filter-based oscillators
161
162 //-------------------------- oscb --------------------------------
163 // Sinusoidal oscillator based on the biquad
164 //
165 oscb(f) = impulse : tf2(1,0,0,a1,1)
166 with {
167 a1 = -2*cos(2*PI*f/SR);
168 };
169
170 //-------------------------- oscr --------------------------------
171 // Sinusoidal oscillator based on 2D vector rotation,
172 // = undamped "coupled-form" resonator
173 // = lossless 2nd-order normalized ladder filter
174 //
175 // Reference:
176 // https://ccrma.stanford.edu/~jos/pasp/Normalized_Scattering_Junctions.html
177 //
178 oscrq(f) = impulse : nlf2(f,1); // sine and cosine outputs
179 oscrs(f) = impulse : nlf2(f,1) : _,!; // sine
180 oscrc(f) = impulse : nlf2(f,1) : !,_; // cosine
181 oscr = oscrs; // default = sine case
182
183 //-------------------------- oscs --------------------------------
184 // Sinusoidal oscillator based on the state variable filter
185 // = undamped "modified-coupled-form" resonator
186 //
187 oscs(f) = (*(0-1) : sint(wn) : sintp(wn,impulse)) ~ _
188 with {
189 wn = 2*PI*f/SR; // approximate
190 // wn = 2*sin(PI*f/SR); // exact
191 sub(x,y) = y-x;
192 sint(x) = *(x) : + ~ _ ; // frequency-scaled integrator
193 sintp(x,y) = *(x) : +(y): + ~ _ ; // same + state input
194 };
195
196 //----------------- oscw, oscwq, oscwc, oscws --------------------
197 // Sinusoidal oscillator based on the waveguide resonator wgr
198 //
199 // oscwc - unit-amplitude cosine oscillator
200 // oscws - unit-amplitude sine oscillator
201 // oscq - unit-amplitude cosine and sine (quadrature) oscillator
202 // oscw - default = oscwc for maximum speed
203 //
204 // Reference:
205 // https://ccrma.stanford.edu/~jos/pasp/Digital_Waveguide_Oscillator.html
206 //
207 oscwc(fr) = impulse : wgr(fr,1) : _,!; // cosine (cheapest at 1 mpy/sample)
208 oscws(fr) = impulse : wgr(fr,1) : !,_; // sine (needs a 2nd scaling mpy)
209 oscq(fr) = impulse : wgr(fr,1); // phase quadrature outputs
210 oscw = oscwc;
211
212 //-------------------------- oscrs_demo ---------------------------
213
214 oscrs_demo = signal with {
215 osc_group(x) = vgroup("[0] SINE WAVE OSCILLATOR oscrs
216 [tooltip: Sine oscillator based on 2D vector rotation]",x);
217 knob_group(x) = osc_group(hgroup("[1]", x));
218 // ampdb = knob_group(vslider("[1] Amplitude [unit:dB] [style:knob]
219 ampdb = knob_group(hslider("[1] Amplitude [unit:dB]
220 [tooltip: Sawtooth waveform amplitude]",
221 -20,-120,10,0.1));
222 amp = ampdb : smooth(0.999) : db2linear;
223 freq = knob_group(
224 // vslider("[2] Frequency [unit:PK] [style:knob]
225 hslider("[2] Frequency [unit:PK]
226 [tooltip: Sine wave frequency as a Piano Key (PK) number (A440 = 49 PK)]",
227 49,1,88,0.01) : pianokey2hz);
228 pianokey2hz(x) = 440.0*pow(2.0, (x-49.0)/12); // (also defined in effect.lib)
229 portamento = knob_group(
230 // vslider("[3] Portamento [unit:sec] [style:knob]
231 hslider("[3] Portamento [unit:sec]
232 [tooltip: Portamento (frequency-glide) time-constant in seconds]",
233 0.1,0,1,0.001));
234 sfreq = freq : smooth(tau2pole(portamento));
235 signal = amp * oscrs(sfreq);
236 };
237
238 oscr_demo = oscrs_demo; // synonym
239
240 //--------------------------- pink_noise --------------------------
241 // Pink noise (1/f noise) generator (third-order approximation)
242 //
243 // USAGE: pink_noise : _;
244 //
245 // Reference:
246 // https://ccrma.stanford.edu/~jos/sasp/Example_Synthesis_1_F_Noise.html
247 //
248
249 pink_noise = noise :
250 iir((0.049922035, -0.095993537, 0.050612699, -0.004408786),
251 (-2.494956002, 2.017265875, -0.522189400));