The "Audio Plug-Ins Designed with Faust" workshop will take place at CCRMA on July 4-8 2016. This page will be updated "on the fly" with the material studied during each day of the workshop. Each Faust code on this page will be posted with its corresponding SVG block diagram and online application. To run the online application, just click on the button that will be placed under the block diagram (if the interface is too big for your screen, just zoom-out). To view the interactive version of the block diagram, click on the button. You can modify the Faust code and see the result by copying and pasting its code in the editing window of the Faust Online Compiler.

Another option is to use the brand new online Faust Playground that allows you to compile Faust objects on the fly directly in your web browser, to connect them together and to export the final result to the FaustWeb online service. Alternatively, your can run Faust Playground locally on your system, just get the source.

WARNING: during this year's workshop, we will be using a new version of Faust libraries that hasn't been integrated to the Faust distribution yet and is accessible on the Faust git repository under the master-new-libraries branch.

For any question/comment/suggestion, please contact me.

Content

GETTING READY: INSTALLING FAUST
   Linux
   MacOSX
   Windows
DAY 1
   Gain Controller
   Sawtooth Synthesizer
   Simple Panner
DAY 2
   Additive Synthesizer
   Ring Modulation
   One Zero Filter
   Flanger
DAY 3
   Auto Panner
   Echo
   Karplus-Strong (Virtual String)
   Feedback Comb Filter
DAY 4
   Distortion
   Filter Bank
   Vocoder
DAY 5
   Freeverb
   Compressor

Getting Ready for the Workshop: Installing Faust

Linux

If you encounter a problem during one of the following steps, feel free to send me an e-mail.

The two main tools that we'll need during the workshop are the Faust compiler and FaustLive. The Faust compiler needs to be compiled from scratch. A pre-compiled version of FaustLive for Ubuntu 64 bits can be downloaded here. If you can use it (you need to use Ubuntu for that), just jump to the next section on how to compile the Faust compiler. If you don't use Ubuntu, you'll have to compile FaustLive. For this, you'll need to compile a specific version of the Faust compiler called faust2. Since we wont use faust2 during the workshop, you will have to recompile the Faust compiler a second time, using the regular "master branch" (that's what this section is about). I know this sounds complicated, but that's how it works unfortunately. Once again, feel free to send me an e-mail if you encounter any problem during this process.

Faust 2 and FaustLive

While the Faust compiler itself was designed to not rely on any external library, some of the tools gravitating around Faust do have a few dependencies. Thus you need to make sure that the following packages are installed on your system before we begin: git, llvm (3.5), llvm-dev (3.5), libmicrohttpd and qjackctl.

For the workshop, we will use some of the latest features of Faust so it is strongly recommended that you compile and install Faust from the Git repository. For that, open a terminal window, cd to the location where you want to download Faust's source code and then type:

git clone git://git.code.sf.net/p/faudiostream/code faudiostream-code
cd faudiostream-code
git checkout faust2
make
sudo make install

Hopefully, everything went well and now if you type: faust and press the return key in your terminal, the following message should be returned: ERROR : no files specified; for help type "faust --help". However, if you get something like faust: command not found, something probably went wrong.

Next, we need to install FaustLive which is an "on-the-fly" compiler for Faust (we'll see during the workshop what this means). It is a great tool that enables you to compile Faust codes "almost in real-time" and that makes programming in Faust very smooth. Don't forget to read the installation instructions contained in the package!!! Otherwise, open a terminal window and cd to the location where you want to download FaustLive's source code and type:

git clone git://git.code.sf.net/p/faudiostream/faustlive faudiostream-faustlive
cd faudiostream-faustlive
make
sudo make install

Hopefully, things went well. To see if it worked just type: FaustLive & in your terminal and the FaustLive interface should appear. If it does, hooray! You're now ready to code in Faust!

Faust

If you already cloned the Faust git in the previous step, the only thing you have to do is to run the following commands are the root of the source code:

git checkout master
make
sudo make install

Otherwise run the following:

git clone git://git.code.sf.net/p/faudiostream/code faudiostream-code
cd faudiostream-code
make
sudo make install

That's it! You should keep Faust's source code for the workshop: it will be probably helpful.

Optionally, you can also get the following packages: lv2-dev, ladspa-sdk, libjack-jackd2-dev and libgtk2.0-dev as well as any dependency related to a specific Faust architecture (to get a non-exhaustive list, just type faust2 in a terminal and then press the TAB key).

MacOSX

In order to install some of Faust's dependencies, you will have to use the terminal of your laptop that you can find in the Applications folder. If you never used it before, keep in mind that you have to press the return key after every command. Commands are indicated in this document using this font. This might sound stupid but don't forget to press the return key to run each command :). If you encounter a problem during one of the following steps, feel free to send me an e-mail.

The first thing you want to do is to install FaustLive. It is an "on-the-fly" compiler for Faust (we'll see during the workshop what this means) that will make your coding experience a very smooth one. For that, download FaustLive and follow the install instructions (very important!!!).

To make sure that it worked, open FaustLive and try to open one of the examples like "harpeautomation". If it makes sound, it's a good sign: you're now ready to start coding in Faust!

While FaustLive is great for prototyping, it's missing many "deeper" features of Faust which is why you should still install the Faust compiler. Before you do that, you should make sure that Xcode (developer and command line tools) is installed on your system.

For the workshop, we will use some of the latest features of Faust so it is strongly recommended that you compile and install Faust from the Git repository. For that, create a new folder in your home directory (or anywhere else) called faust. Open a terminal window, and type: cd faust which means "go to the faust folder" from your home directory and press the return key. After that, type the following commands to download, compile and install the Faust compiler:

git clone git://git.code.sf.net/p/faudiostream/code faudiostream-code
cd faudiostream-code
make
sudo make install

You should keep the faust folder for the workshop: it will be probably helpful. If things went well, Faust should now be installed on your system. To make sure that it is the case, type: faust and press the return key in your terminal, the following message should be returned: ERROR : no files specified; for help type "faust --help". However, if you get something like faust: command not found, something probably went wrong.

Lastly, you might want to install the VST SDK on your system if you want to generate VST plug-ins. For that, download this file and unzip it. Open a new terminal window and cd to the folder where you unziped the file and then type: sudo mv vstsdk2.4 /usr/local/include/. After this step, you should be able to compile any Faust code into a VST plug-in by simply typing faust2faustvst yourFaustFile.dsp in a terminal. Albert Graef implemented the current version of this architecture and I strongly recommend you to check its documentation before doing it.

Optionally, you can also get any dependency related to a specific Faust architecture (to get a non-exhaustive list, just type faust2 in a terminal and then press the TAB key). Feel free to contact me if you have a question about that.

Windows

If you encounter a problem during one of the following steps, feel free to send me an e-mail.

Installing the Faust compiler on Windows can be complicated but fortunately, this is not the case of FaustLive that is an "on-the-fly" compiler for Faust (we'll see during the workshop what this means). For that, just download this file and follow the instructions. If you're a Jack user, you might want to check this version. Don't forget to read the installation instructions contained in the package!!! Once this is done, you can try to run one of the examples like "harpeautomation". If it makes sound, it's a good sign: you're ready to code in Faust!

You should download the latest version of the source code of the Faust compiler by clicking on the "Download Snapshot" button on this page and leave it somewhere on your system as it will be very helpful during the workshop.

Lastly, if you don't already have one, you should download an "more advanced" text editor than notepad, etc. I recommend using Notepad++ for example.

Day 1

Check out Julius Smith's book series on signal processing to get a better understanding of the different algorithms that will be studied during the workshop.

Check out this page to have more details on how loudness is perceived.

Faust's documentation can be found here. It contains most of the basic examples that we studied in class on how to work with the different signal operators (<:, :>, : , etc.).

Simple Gain Controller

import("stdfaust.lib");
gain = hslider("gain",0.5,0,1,0.01) : si.smoo;
process = *(gain);

Sawtooth Synthesizer

import("stdfaust.lib");
freq = hslider("freq",400,100,2000,0.01) : si.smoo;
gain = hslider("gain",0.5,0,1,0.01) : si.smoo;
trigger = button("gate") : si.smoo;
synth = os.sawtooth(freq)*gain*trigger;
process = synth;

Simple Panner

import("stdfaust.lib");
pan = hslider("pan",0.5,0,1,0.01) : si.smoo;
process = _ <: *(1-pan),*(pan);

Day 2

Additive Synthesizer

Reference: https://ccrma.stanford.edu/~jos/pasp/Additive_Synthesis.html

import("stdfaust.lib");
nOsc = 3;
freq = hslider("freq",400,100,2000,0.01) : si.smoo;
gain = hslider("gain",0.5,0,1,0.01) : si.smoo;
trigger = checkbox("gate") : si.smoo;
process = par(i,nOsc,os.osc(freq*(i+1))) :> *(gain*trigger)/nOsc;

Ring Modulation

Reference: https://ccrma.stanford.edu/~jos/rbeats/Sinusoidal_Amplitude_Modulation_AM.html

import("stdfaust.lib");
frequency = hslider("frequency",8,0.01,5000,0.01) : si.smoo;
dpth = hslider("depth",0,0,1,0.01) : si.smoo;

ringMod(freq,depth) = *(modSig)
with{
	modSig = 1 - (os.osc(freq)+1)*0.5*depth;
};

process = ringMod(frequency,dpth);

One Zero Filter

Reference: https://ccrma.stanford.edu/~jos/fp/One_Zero.html

import("stdfaust.lib");
b = hslider("b",0,-1,1,0.01) : si.smoo;
oneZero(b1) = _ <: (_' : *(b1)),_ : + ;
process = oneZero(b);

Flanger (and Feed-Forward Comb Filter)

Reference: https://ccrma.stanford.edu/~jos/pasp/Flanging.html.

import("stdfaust.lib");
flangerMaxDelay = vslider("[2]Delay[style:knob]",10,0,20,0.01)*0.001*ma.SR : si.smoo;
flangerDepth = vslider("[1]Depth[style:knob]",0,0,1,0.01) : si.smoo;
flangerSpeed = vslider("[0]Speed[style:knob]",1,0.1,10,0.01) : si.smoo;
comb(delLength,b1) = _ <: (de.fdelay4(2048,delLength) : *(b1)),_ : + ;
flanger(maxDelay,depth,speed) = comb(delLength,depth)
with{
	delLength = maxDelay*(os.osc(speed)+1)/2;
};
process = vgroup("[1]Flanger",par(i,2,flanger(flangerMaxDelay,flangerDepth,flangerSpeed)));

Day 3

Auto Panner

import("stdfaust.lib");
freq = hslider("freq",5,0.1,500,0.01) : si.smoo;
pan = (os.osc(freq)+1)/2;
process = _ <: *(1-pan),*(pan);

Echo

import("stdfaust.lib");
d = hslider("Duration",0.5,0,1,0.01) : si.smoo;
f = hslider("Feedback",0,0,1,0.01) : si.smoo;
echo(duration,feedback) = +~(de.delay(ma.np2(44100),delayLength) : *(feedback))
with{
	delayLength = duration*ma.SR-1;
};
process = par(i,2,echo(d,f));

Karplus-Strong

Reference: https://ccrma.stanford.edu/~jos/pasp/Karplus_Strong_Algorithm.html

import("stdfaust.lib");
freq = hslider("freq",400,50,2000,0.01) : si.smoo;
f = hslider("feedback",0.99,0,1,0.01) : si.smoo;
gate = button("pluck");
string(frequency,feedback) = +~(de.fdelay4(ma.np2(1000),delayLength) : *(feedback) <: (_+_')/2)
with{
	delayLength = ma.SR/frequency-1;
};
process = gate : ba.impulsify : string(freq,f);

Feedback Comb Filter

Reference: https://ccrma.stanford.edu/~jos/pasp/Feedback_Comb_Filters.html

import("stdfaust.lib");
d = hslider("delayLength",1,0,100,1);
f = hslider("feedback",0,0,1,0.01) : si.smoo;
fComb(delayLength,feedback) = +~(de.delay(ma.np2(100),delayLength) : *(feedback));
process = fComb(d,f);

Day 4

Distortion

Reference: https://ccrma.stanford.edu/~jos/pasp/Memoryless_Nonlinearities.html

import("stdfaust.lib");
d = hslider("drive",0,0,1,0.01) : si.smoo;
o = hslider("offset",0,-1,1,0.01) : si.smoo;
distortion(drive,offset) = +(offset) : *(pregain) : clip : cubic : fi.dcblocker
with{
	pregain = pow(10,2*drive); // pregain range is 0 - 100
	clip = min(1) : max(-1); // clip the signal between 1 and -1
	cubic(x) = x - pow(x,3)/3;
};
process = distortion(d,o);

Filter Bank

Reference: https://ccrma.stanford.edu/realsimple/aud_fb/What_Filter_Bank.html

import("stdfaust.lib");
nBands = 8;
filterBank(N) = hgroup("Filter Bank",seq(i,N,oneBand(i)))
with{
	oneBand(j) = vgroup("[%j]Band %a",fi.peak_eq(l,f,b))
	with{
		a = j+1; // just so that band numbers don't start at 0
		l = vslider("[2]Level[unit:db]",0,-70,12,0.01) : si.smoo;
		f = nentry("[1]Freq",(80+(1000*8/N*(j+1)-80)),20,20000,0.01) : si.smoo;
		b = f/hslider("[0]Q[style:knob]",1,1,50,0.01) : si.smoo;
	};
};
process = filterBank(nBands);

Vocoder

References:

import("stdfaust.lib");
bands = 32;
exFreq = hslider("Excitation Frequency[unit:Hz]",150,70,1500,0.01) : si.smoo;
attDuration = hslider("[0]Attack Duration[style:knob][unit:ms]",0.1,0.01,100,0.01)*0.001 : si.smoo;
relDuration = hslider("[1]Release Duration[style:knob][unit:ms]",1,0.01,100,0.01)*0.001 : si.smoo;
filtersQ = hslider("[2]Q[style:knob]",15,1,30,0.01) : si.smoo;
vocoder(nBands,att,rel,q,source,excitation) = source <: par(i,nBands,oneAnalysisBand(i) : 
	oneSynthesisBand(i)) :> _
with{
	oneAnalysisBand(j) = fi.resonbp(freq,q,1) : an.amp_follower_ud(att,rel)
	with{
		freq = 25*pow(2,(j+1)*(9/nBands));
	};
	
	oneSynthesisBand(j) = _,excitation : fi.resonbp(freq,q)
	with{
		freq = 25*pow(2,(j+1)*(9/nBands));
	};
};
process = _,vgroup("[1]Sawtooth",os.sawtooth(exFreq)) : 
	hgroup("[0]Vocoder",vocoder(bands,attDuration,relDuration,filtersQ));

Day 5

Freeverb

References: https://ccrma.stanford.edu/~jos/pasp/Freeverb.html

import("stdfaust.lib");
origSR = 44100;
freeverb(fb1,fb2,damp,spread) = _ <: par(i,8,lbcf(combtuningL(i)+spread,fb1,damp)) :> 
	seq(i,4,fi.allpass_comb(1024,allpasstuningL(i)+spread,fb2))
with{
	dLall = (556,441,341,225);
	allpasstuningL(i) = ba.take(i+1,dLall)*ma.SR/origSR;
	
	dLcomb = (1116,1188,1277,1356,1422,1491,1557,1617);
	combtuningL(i) = ba.take(i+1,dLcomb)*ma.SR/origSR;
	
	lbcf(dt,fb,damp) = (+:@(dt)) ~ (*(1-damp) : (+~*(damp)) : *(fb));
};
stereo_freeverb(fb1,fb2,damp,spread) = + <: freeverb(fb1,fb2,damp,0),
	freeverb(fb1,fb2,damp,spread);
scaleroom = 0.28;
offsetroom = 0.7;
allpassfeed = 0.5;
scaledamp = 0.4;
fixedgain = 0.1;
combfeed = hslider("Room Size",0.5,0,1,0.025)*scaleroom*ma.SR/origSR + offsetroom;
damping = hslider("Damping",0.5,0,1,0.025)*scaledamp*ma.SR/origSR;
spatSpread = hslider("Stereo Spread",0.5,0,1,0.01)*46*ma.SR/origSR;
g = hslider("Dry/Wet",0.333,0,1,0.01);
process = _,_ <: 
	(*(g)*fixedgain,*(g)*fixedgain : stereo_freeverb(combfeed,allpassfeed,damping,spatSpread)),
	*(1-g),*(1-g) :> _,_;

Compressor

References: https://ccrma.stanford.edu/~jos/fp/Nonlinear_Filter_Example_Dynamic.html

import("stdfaust.lib");
vCompGain = hbargraph("[5]Compressor Gain[unit:dB]",-50,10);
vGain = hbargraph("[6]Input Gain[unit:dB]",-50,10);
compressor(ratio,thresh,att,rel,kneeAtt) = _ <: *(an.amp_follower_ud(att,rel) : 
	ba.linear2db : vGain : outminusdb(ratio,thresh) : kneesmooth(kneeAtt) : 
	vCompGain : ba.db2linear)
with{
	outminusdb(ratio,thresh,level) = max(level-thresh,0)*(1/ratio-1);
	kneesmooth(att) = si.smooth(ba.tau2pole(att));
};
ratio = hslider("[0]Ratio",1,1,20,0.001) : si.smoo;
thresh = hslider("[1]Threshold[unit:dB]",-30,-60,0,0.01) : si.smoo;
att = hslider("[2]Attack[unit:ms]",50,0,500,0.1)*0.001;
rel = hslider("[3]Release[unit:ms]",100,0,1000,0.1)*0.001;
kneeAtt = hslider("[4]Knee Attack[unit:ms]",25,0,500,0.1)*0.001;
process = vgroup("Compressor",compressor(ratio,thresh,att,rel,kneeAtt));