New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / examples / faust-stk / instrument.lib
diff --git a/interpretor/preprocessor/faust-0.9.47mr3/examples/faust-stk/instrument.lib b/interpretor/preprocessor/faust-0.9.47mr3/examples/faust-stk/instrument.lib
new file mode 100644 (file)
index 0000000..dffdbeb
--- /dev/null
@@ -0,0 +1,298 @@
+//instrument.lib - Faust function of various types usefull for building physical model instruments 
+
+declare name "Faust-STK Tools Library";
+declare author "Romain Michon (rmichon@ccrma.stanford.edu)";
+declare copyright "Romain Michon";
+declare version "1.0";
+declare licence "STK-4.3"; // Synthesis Tool Kit 4.3 (MIT style license);
+
+import("math.lib");
+import("filter.lib");
+import("effect.lib");
+
+//========================= ENVELOPE GENERATORS ===============================
+
+//----------------------- VIBRATO ENVELOPE ----------------------------
+// 4 phases envelope to control vibrato gain
+//
+// USAGE: 
+//   _ : *(envVibrato(b,a,s,r,t)) : _
+// where
+//   b = beginning duration (silence) in seconds
+//   a = attack duration in seconds
+//   s = sustain as a percentage of the amplitude to be modified
+//   r = release duration in seconds
+//   t = trigger signal 
+
+envVibrato(b,a,s,r,t) = env ~ (_,_,_) : (!,!,_) // the 3 'state' signals are fed back
+with {
+    env (p2,cnt,y) =
+        (t>0) & (p2|(y>=1)),
+               (cnt + 1)*(t>0), // counter for the first step "b" 
+        (y + p1*p3*u*(s/100) - p4*w*y)*((p4==0)|(y>=eps))      // y  = envelop signal
+               //*(y>=eps) // cut off tails to prevent denormals
+    with {
+       p1 = (p2==0) & (t>0) & (y<1) & (cnt>(b*SR)); // p1 = attack phase
+       p3 = 1-(cnt<(nb)); // p3 = beginning phase
+       p4 = (t<=0) & (y>0);  // p4 = release phase
+       // #samples in attack, release, must be >0
+       nb = SR*b+(b==0.0) ; na = SR*a+(a==0.0); nr = SR*r+(r==0.0);
+       // attack and (-60dB) release rates
+       z = s+(s==0.0)*db2linear(-60);
+       u = 1/na; w = 1-1/pow(z*db2linear(60), 1/nr);
+       // values below this threshold are considered zero in the release phase
+       eps = db2linear(-120);
+    };
+};
+
+//----------------------- ATTACK - SUSTAIN - RELEASE ----------------------------
+// Attack - Sustain - Release envelope
+//
+// USAGE: 
+//   _ : *(asr(a,s,r,t)) : _
+// where
+//   a = attack duration in seconds
+//   s = sustain as a percentage of the amplitude to be modified
+//   r = release duration in seconds
+//   t = trigger signal 
+
+asr(a,s,r,t) = env ~ (_,_) : (!,_) // the 2 'state' signals are fed back
+with {
+    env (p2,y) =
+        (t>0) & (p2|(y>=1)),
+        (y + p1*u*(s/100) - p3*w*y)    // y  = envelop signal
+       *((p3==0)|(y>=eps)) // cut off tails to prevent denormals
+    with {
+       p1 = (p2==0) & (t>0) & (y<1); // p1 = attack phase
+       p3 = (t<=0) & (y>0); // p3 = release phase
+       // #samples in attack, release, must be >0
+       na = SR*a+(a==0.0); nr = SR*r+(r==0.0);
+       // correct zero sustain level
+       z = s+(s==0.0)*db2linear(-60);
+       // attack and (-60dB) release rates
+       u = 1/na; w = 1-1/pow(z*db2linear(60), 1/nr);
+       // values below this threshold are considered zero in the release phase
+       eps = db2linear(-120);
+    };
+};
+
+//----------------------- ASYMPT60 ----------------------------
+// Envelope generator which asymptotically approaches a target value.
+//
+// USAGE: 
+//   asympT60(value,trgt,T60,trig) : _
+// where
+//   value = starting value
+//   trgt = target value
+//   T60 = ramping time
+//   trig = trigger signal 
+
+asympT60(value,trgt,T60,trig) = (_*factor + constant)~_
+       with{
+               cntSample = *(trig) + 1~_ : -(1);
+               attDur = float(2);
+               cndFirst = ((cntSample < attDur) & (trig > 0));
+               target = value*cndFirst + trgt*(cndFirst < 1);
+               factorAtt = exp(-7/attDur);
+               factorT60 = exp(-7/(T60*float(SR)));
+               factor = factorAtt*((cntSample < attDur) & (trig > 0)) + 
+                      ((cntSample >= attDur) | (trig < 1))*factorT60;
+               constant = (1 - factor)*target; 
+       };
+
+//========================= TABLES ===============================
+
+//----------------------- CLIPPING FUNCTION ----------------------------
+// Positive and negative clipping functions.
+//
+// USAGE: 
+//   _ : saturationPos : _
+//   _ : saturationNeg : _
+//   _ : saturationPos : saturationNeg : _
+
+saturationPos(x) = x <: (_>1),(_<=1 : *(x)) :> +;
+saturationNeg(x) = x <: (_<-1),(_>=-1 : *(x)) :> *(-1) + _;
+
+//----------------------- BOW TABLE ----------------------------
+// Simple bow table.
+//
+// USAGE: 
+//   index : bow(offset,slope) : _
+// where
+//   0 <= index <= 1 
+
+bow(offset,slope) = pow(abs(sample) + 0.75, -4) : saturationPos
+       with{
+       sample(y) = (y + offset)*slope;
+       };
+
+//----------------------- REED TABLE ----------------------------
+// Simple reed table to be used with waveguide models of clanrinet, saxophone, etc.
+//
+// USAGE:
+//   _ : reed(offset,slope) : _
+// where
+//   offset = offset between 0 and 1
+//   slope = slope between 0 and 1
+// REFERENCE:
+//   https://ccrma.stanford.edu/~jos/pasp/View_Single_Reed_Oscillation.html
+
+reed(offset,slope) = reedTable : saturationPos : saturationNeg
+       with{
+       reedTable = offset + (slope*_);
+       };
+
+//========================= FILTERS ===============================
+
+//----------------------- ONE POLE ----------------------------
+
+onePole(b0,a1,x) = (b0*x - a1*_)~_;
+
+//----------------------- ONE POLE SWEPT ----------------------------
+
+onePoleSwep(a1,x) = (1 + a1)*x - a1*x';
+
+//----------------------- POLE ZERO ----------------------------
+
+poleZero(b0,b1,a1,x) = (b0*x + b1*x' - a1*_)~_;
+
+//----------------------- ONE ZEROS ----------------------------
+// Simple One zero and One zero recursive filters
+//
+// USAGE:
+//   _ : oneZero0(b0,b1) : _
+//   _ : oneZero1(b0,b1) : _
+// REFERENCE:
+//   https://ccrma.stanford.edu/~jos/fp2/One_Zero.html
+
+oneZero0(b0,b1,x) = (*(b1) + x*b0)~_;
+oneZero1(b0,b1,x) = (x'*b1 + x*b0);
+
+//----------------------- BANDPASS FILTER WITH CONSTANT UNITY PEAK GAIN BASED ON A BIQUAD ----------------------------
+
+bandPass(resonance,radius) = TF2(b0,b1,b2,a1,a2)
+       with{
+               a2 = radius*radius;
+               a1 = -2*radius*cos(PI*2*resonance/SR);
+               b0 = 0.5-0.5*a2;
+               b1 = 0;
+               b2 = -b0;
+       };
+
+//----------------------- BANDPASS FILTER BASED ON A BIQUAD ----------------------------
+// Band pass filter using a biquad (TF2 is declared in filter.lib)
+//
+// USAGE:
+//   _ : bandPassH(resonance,radius) : _
+// where
+//   resonance = center frequency
+//   radius = radius
+
+bandPassH(resonance,radius) = TF2(b0,b1,b2,a1,a2)
+       with{
+               a2 = radius*radius;
+               a1 = -2*radius*cos(PI*2*resonance/SR);
+               b0 = 1;
+               b1 = 0;
+               b2 = 0;
+       };
+
+//----------------------- FLUE JET NON-LINEAR FUNCTION ----------------------------    
+// Jet Table: flue jet non-linear function, computed by a polynomial calculation
+       
+jetTable(x) = x <: _*(_*_-1) : saturationPos : saturationNeg;
+
+//----------------------- NON LINEAR MODULATOR ----------------------------
+// nonLinearModulator adapts the function allpassnn from filter.lib for using it with waveguide instruments
+//
+// USAGE:
+//   _ : nonLinearModulator(nonlinearity,env,freq,typeMod,freqMod,order) : _
+// where
+//   nonlinearity = nonlinearity coefficient between 0 and 1 
+//   env = input to connect any kind of envelope
+//   freq = current tone frequency
+//   typeMod = if 0: theta is modulated by the incoming signal;
+//            if 1: theta is modulated by the averaged incoming signal;
+//            if 2: theta is modulated by the squared incoming signal;
+//            if 3: theta is modulated by a sine wave of frequency freqMod;
+//            if 4: theta is modulated by a sine wave of frequency freq;
+//   freqMod = frequency of the sine wave modulation
+//   order = order of the filter
+nonLinearModulator(nonlinearity,env,freq,typeMod,freqMod,order) = 
+       //theta is modulated by a sine wave
+       _ <: nonLinearFilterOsc*(typeMod >= 3),
+       //theta is modulated by the incoming signal
+            (_ <: nonLinearFilterSig*nonlinearity,_*(1 - nonlinearity) :> +)*(typeMod < 3)
+       :> +
+       with{
+               //which frequency to use for the sine wave oscillator?
+               freqOscMod = (typeMod == 4)*freq + (typeMod != 4)*freqMod;
+
+               //the incoming signal is scaled and the envelope is applied
+               tsignorm(x) = nonlinearity*PI*x*env;
+               tsigsquared(x) = nonlinearity*PI*x*x*env; //incoming signal is squared
+               tsigav(x) = nonlinearity*PI*((x + x')/2)*env; //incoming signal is averaged with its previous sample
+               
+               //select which version of the incoming signal of theta to use
+               tsig(x) = tsignorm(x)*(typeMod == 0) + tsigav(x)*(typeMod == 1) 
+                         + tsigsquared(x)*(typeMod == 2);
+
+               //theta is modulated by a sine wave generator
+               tosc = nonlinearity*PI*osc(freqOscMod)*env; 
+
+               //incoming signal is sent to the nonlinear passive allpass ladder filter
+               nonLinearFilterSig(x) = x <: allpassnn(order,(par(i,order,tsig(x))));
+               nonLinearFilterOsc = _ <: allpassnn(order,(par(i,order,tosc)));
+       };
+       
+//========================= WAVE TABLES ===============================
+
+//----------------------- STICK IMPACT ----------------------------
+// Stick impact table.
+//
+// USAGE:
+//   index : readMarmstk1 : _
+
+readMarmstk1 = ffunction(float readMarmstk1 (int), <instrument.h>,"");
+marmstk1TableSize = 246;
+
+//========================= TOOLS ===============================
+
+//----------------------- STEREOIZER ----------------------------
+// This function takes a mono input signal and spacialize it in stereo 
+// in function of the period duration of the tone being played.
+//
+// USAGE:
+//   _ : stereo(periodDuration) : _,_
+// where
+//   periodDuration = period duration of the tone being played in number of samples 
+// ACKNOWLEDGMENT
+//   Formulation initiated by Julius O. Smith in https://ccrma.stanford.edu/realsimple/faust_strings/          
+
+stereoizer(periodDuration) = _ <: _,widthdelay : stereopanner
+          with{
+               W = hslider("v:Spat/spatial width", 0.5, 0, 1, 0.01);
+               A = hslider("v:Spat/pan angle", 0.6, 0, 1, 0.01);
+               widthdelay = delay(4096,W*periodDuration/2);
+               stereopanner = _,_ : *(1.0-A), *(A);
+          };
+
+//----------------------- INSTRREVERB ----------------------------
+// GUI for zita_rev1_stereo from effect.lib
+//
+// USAGE:
+//  _,_ : instrRerveb
+
+instrReverb = _,_ <: *(reverbGain),*(reverbGain),*(1 - reverbGain),*(1 - reverbGain) : 
+zita_rev1_stereo(rdel,f1,f2,t60dc,t60m,fsmax),_,_ <: _,!,_,!,!,_,!,_ : +,+
+       with{
+       reverbGain = hslider("v:Reverb/reverbGain",0.137,0,1,0.01) : smooth(0.999);
+       roomSize = hslider("v:Reverb/roomSize",0.72,0.01,2,0.01);
+       rdel = 20;
+       f1 = 200;
+       f2 = 6000;
+       t60dc = roomSize*3;
+       t60m = roomSize*2;
+       fsmax = 48000;
+       };