1declare name "NLFfm";
2declare description "FM synthesizer implemented with a nonlinear passive allpass filter";
3declare author "Romain Michon (rmichon@ccrma.stanford.edu)";
4declare copyright "Romain Michon";
5declare version "1.0";
6declare nvoices "16";
7
8import("instrument.lib");
9import("music.lib");
10
11//==================== GUI SPECIFICATION ================
12
13freq = nentry("h:Basic_Parameters/freq [1][unit:Hz] [tooltip:Tone frequency]",440,20,20000,1);
14gain = nentry("h:Basic_Parameters/gain [1][tooltip:Gain (value between 0 and 1)]",0.8,0,1,0.01);
15gate = button("h:Basic_Parameters/gate [1][tooltip:noteOn = 1, noteOff = 0]");
16
17typeModulation = nentry("h:Physical_and_Nonlinearity/v:Nonlinear_Filter_Parameters/Modulation_Type
18[2][tooltip: 0=theta is modulated by the incoming signal; 1=theta is modulated by the averaged incoming signal;
192=theta is modulated by the squared incoming signal; 3=theta is modulated by a sine wave of frequency freqMod;
204=theta is modulated by a sine wave of frequency freq;][lv2:integer]",0,0,4,1);
21nonLinearity = hslider("h:Physical_and_Nonlinearity/v:Nonlinear_Filter_Parameters/Nonlinearity
22[2][tooltip:Nonlinearity factor (value between 0 and 1)]",0,0,1,0.01);
23frequencyMod = hslider("h:Physical_and_Nonlinearity/v:Nonlinear_Filter_Parameters/Modulation_Frequency
24[2][unit:Hz][tooltip:Frequency of the sine wave for the modulation of theta (works if Modulation Type=3)]",220,20,1000,0.1);
25nonLinAttack = hslider("h:Physical_and_Nonlinearity/v:Nonlinear_Filter_Parameters/Nonlinearity_Attack
26[2][unit:s][Attack duration of the nonlinearity]",0.1,0,2,0.01);
27
28vibratoFreq = hslider("h:Envelopes_and_Vibrato/v:Vibrato_Parameters/Vibrato_Freq
29[3][unit:Hz]",5,1,15,0.1);
30vibratoGain = hslider("h:Envelopes_and_Vibrato/v:Vibrato_Parameters/Vibrato_Gain
31[3][tooltip:A value between 0 and 1]",0.1,0,1,0.01);
32vibratoAttack = hslider("h:Envelopes_and_Vibrato/v:Vibrato_Parameters/Vibrato_Attack
33[3][unit:s][tooltip:Vibrato attack duration]",0.5,0,2,0.01);
34vibratoRelease = hslider("h:Envelopes_and_Vibrato/v:Vibrato_Parameters/Vibrato_Release
35[3][unit:s][tooltip:Vibrato release duration]",0.01,0,2,0.01);
36
37envelopeAttack = hslider("h:Envelopes_and_Vibrato/v:Envelope_Parameters/Envelope_Attack
38[4][unit:s][tooltip:Envelope attack duration]",0.05,0,2,0.01);
39envelopeDecay = hslider("h:Envelopes_and_Vibrato/v:Envelope_Parameters/Envelope_Decay
40[4][unit:s][tooltip:Envelope decay duration]",0.05,0,2,0.01);
41envelopeRelease = hslider("h:Envelopes_and_Vibrato/v:Envelope_Parameters/Envelope_Release
42[4][unit:s][tooltip:Envelope release duration]",0.05,0,2,0.01);
43
44//----------------------- Nonlinear filter ----------------------------
45//nonlinearities are created by the nonlinear passive allpass ladder filter declared in filter.lib
46
47//nonlinear filter order
48nlfOrder = 3;
49
50//attack - sustain - release envelope for nonlinearity (declared in instrument.lib)
51envelopeMod = asr(nonLinAttack,100,envelopeRelease,gate);
52
53//nonLinearModultor is declared in instrument.lib, it adapts allpassnn from filter.lib
54//for using it with waveguide instruments
55NLFM =  nonLinearModulator((nonLinearity : smooth(0.999)),envelopeMod,freq,
56     typeModulation,(frequencyMod : smooth(0.999)),nlfOrder);
57
58//----------------------- Algorithm implementation ----------------------------
59
60//stereoizer is declared in instrument.lib and implement a stereo spacialisation in function of
61//the frequency period in number of samples
62stereo = stereoizer(SR/freq);
63
64//vibrato gain is controled by envVibrato (declared in instrument.LIB)
65vibrato = osc(vibratoFreq)*vibratoGain*envVibrato(0.1*2*vibratoAttack,0.9*2*vibratoAttack,100,vibratoRelease,gate);
66
67//output gain is controled by an adsr envelope
68envelope = adsr(envelopeAttack,envelopeDecay,90,envelopeRelease,gate)*gain;
69breath = envelope + envelope*vibrato;
70
71process = stkmain((osc(freq)*breath : NLFM : stereo : instrReverb));
72