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