The goal of this first step is to add MIDI support to a simple synthesizer written in Faust. For this to work, you must use an up-to-date version of Google Chrome. Chrome is the only browser providing MIDI support so using a different one (e.g., Firefox) will not work. There are 3 MIDI interfaces in the MaxLab and one in studio E and D that you can use for this exercise. They all work with USB and some of them need to be powered with an external power supply (that you should find with them).
Say we have this simple synthesizer (feel free to copy this code and paste in the Faust online editor):
import("stdfaust.lib"); freq = hslider("freq",300,50,2000,0.01) : si.smoo; gain = hslider("gain",0.8,0,1,0.01) : si.smoo; process = os.sawtooth(freq)*gain;
Note the use of
si.smooon all its parameters to prevent clicking.
We would like to control
gain using a MIDI interface. To assign a specific MIDI controller (i.e., a knob, a slider, etc.) to a Faust parameter, a metadata must be used. MIDI controllers on a MIDI interface are numbered from 0 to 127. There’s a white tape on the interfaces in the MaxLab indicating which number is assigned to which controller. The interfaces in studio D and E are a bit fancier, and the
ctrl number should be displayed on their screen when interacting with the controller.
Say we’d like to assign a knob whose number is 11 to
freq and another knob with number 55 to
gain, all we have to write is the following:
import("stdfaust.lib"); freq = hslider("freq[midi: ctrl 11]",300,50,2000,0.01) : si.smoo; gain = hslider("gain[midi: ctrl 55]",0.8,0,1,0.01) : si.smoo; process = os.sawtooth(freq)*gain;
Now try to assign knobs on of the interfaces available at CCRMA to
gain to see how this works. Note that the minimum value of the Faust parameter (i.e., 50 for
freq) will be assigned to the lowest position of the knob and that its maximum value (i.e., 2000 for
freq) to the highest position of the knob.
For further information on MIDI support in Faust, please refer to the corresponding section in the Faust documentation.
The Faust distribution comes with a series of libraries implementing a wide range of synthesizers, audio effects, etc. The source code of the Faust libraries can be found in the Faust Libraries repository on GitHub: https://github.com/grame-cncm/faustlibraries. Also, the documentation of the Faust libraries is available on the Faust website: https://faust.grame.fr/doc/libraries/
.lib file contains the source code of a specific library.
All standard Faust libraries are accessible through a series of prefixes declared in
stdfaust.lib. For example, to call the sine oscillator function (
osc) declared in
oscillators.lib, one might write:
import("oscillators.lib"); process = osc(440);
import("stdfaust.lib"); process = os.osc(440);
Some functions of the Faust libraries host their own user interface. Most of these functions are declared in
physmodels.lib. For example, a ready-to-use clarinet physical model can be found
physmodels.lib and called with just 2 lines of code:
import("stdfaust.lib"); process = pm.violin_ui;
Exploring the source code of
physmodels.lib, the declaration of the
violin_ui function can be easily found: https://github.com/grame-cncm/faustlibraries/blob/master/physmodels.lib#L1474
As an exercise, try to write your own version of
my_violin_ui) where some of the parameters of the model are controlled using one of the MIDI interfaces available at CCRMA (hint: don’t forget to add
pm when you call
violinModel since you’ll be outside of
Vibrato is a crucial esthetic feature when performing with some musical instruments in western music. Moreover, in the case of sound synthesis it can help make the harmonic content of a sound more “coherent” (effect of source segregation).
Vibrato can be implemented in Faust simply by modulating the pitch of the generated sound with a sine wave oscillator (e.g.,
pitch + osc(vibratoFreq)*vibratoAmp).
Try to modify the previous example by adding 2 user interface elements to control the frequency and the amplitude of the vibrato. The frequency shouldn’t exceed 10Hz and a good default value is 6Hz. Also, map these 2 new parameters to MIDI controllers on the interface.
Hint: don’t forget that a sine function has both positive and negative values.
vaeffects.lib contain a wide range of audio effects. Some of them have a demo version (with a built-in UI) that can be found in
demos.lib. This table gives of an overview of the most standard audio effects available in the Faust libraries.
We’d like to “improve” our instrument from the previous step (violin with vibrato) with a phasor. A stereo phaser is available in
demos.lib: https://github.com/grame-cncm/faustlibraries/blob/master/demos.lib#L477. Copy its code in your Faust program and rename it as we did for
my_phaser2_demo). Connect the output of
my_violin_ui has one output and
my_phaser2_demo has 2 inputs (stereo), we must use the split operator:
process = my_violin_ui <: my_phaser2_demo;
Try to assign some of the parameters of the phaser to MIDI controllers on the interface that you’re using. Keep in mind that a Faust parameter can contain multiple metadata (i.e.,
speed = ctl_group(hslider(" Speed [unit:Hz] [style:knob][midi: ctrl 26]",0.5,0,10,0.001)))
physmodels.lib, the Faust examples page, and of the Faust 250a starter codes. Also have a look at the Standard Functions section of the Faust libraries documentation.