Next  |  Prev  |  Top  |  JOS Index  |  JOS Pubs  |  JOS Home  |  Search

Using FAUST with Open Sound Control (OSC)

FAUST contains some very nice Open Sound Control (OSC) support facilities [2,9]. OSC, which can be viewed as a generalized replacement for MIDI, is often used for messaging between music applications, even across networks. It is used, for example, as the communication protocol between the SuperCollider client (sclang) and server (scsynth). It is also the protocol of choice for messages from external controllers, such as iOS/Android applications running on tablets.

OSC uses the User Datagram Protocol (UDP) to send and receive messages. UDP is like TCP/IP (the more typical internet message protocol) except that message delivery is not guaranteed. In other words, if some process gets behind and a message is dropped, nobody worries about it. FAUST OSC support makes use of three UDP ports for input, output, and errors. By default these are the UDP ports numbered 5510, 5511, and 5512, respectively; when necessary, FAUST will try higher numbers until a free UDP port is found.

To send an OSC message to some process on some host on the Internet, one needs to know the host's IP address, the UDP port used by the process for receiving, and a ``name path'' (much like a UNIX file path) to the control being affected. The path starts with the application name and includes all group names down to the control name itself. For example, in the zita_rev1.dsp example below, the path to the ``dry-wet mix'' slider is /Zita_Rev1/Output/Dry_Wet_Mix, where Zita_Rev1 is the name of the application, Output is a control group defined in the FAUST source, and Dry_Wet_Mix is the name of the control slider itself within the Output group.

We will use three shells for the examples below, each in its own Terminal window. In Window 1, we will run a FAUST standalone JACK application that will receive OSC messages on UDP port 5510 and respond on port 5511. In Window 2, we will run oscdump (distributed with the liblo package) to print out OSC message activity on port 5511. In Window 3, we will run oscsend (also from liblo) to send OSC messages to port 5510, where the FAUST JACK app is listening. Any responses from the app will appear in Window 2.

Since we are using a standalone JACK application for these examples, remember to start the JACK daemon jackd (via qjackctl on Linux or JackPilot on the Mac). If you forget, jackd will be autolaunched with default setup parameters from your $ \sim$ /.jackdrc configuration file.

Below, comments and program printout are on lines beginning with `#'.



In Terminal Window 1 (application window):

> cd <faust>/examples/generator/
    > faust2jack -osc noise.dsp
      # Drill down on /usr/local/bin/faust2jack and its output to see all the code "under the hood".
    > ./noise
      # After perhaps some delay (especially if JACK is autolaunched), you should see
      #   ...
      #   Faust OSC version 0.91 application 'noise' is running on UDP ports 5510, 5511, 5512
      #   ...
The UDP port numbers are for input, output, and error messages, respectively.



In Terminal Window 2 (OSC dump window):

    > oscdump 5511
      # watch this space for OSC message replies from the Faust JACK app

In Terminal Window 3 (OSC send window):

    > oscsend localhost 5510 /\* s "hello"
      # Window 2 receives the following, after some seconds of delay:
      # /noise siii "0.0.0.0" 5510 5511 5512
Notice the use of 's' to indicate that a string follows. Note that \* is passed to oscsend as *. We are just quoting it to avoid shell filename expansion here. On Red Hat Fedora 17 Linux (liblo v0.26), say 0 in place of localhost above. On a remote machine, use the server-machine's IP address in place of localhost.
    > oscsend localhost 5510 /\* s "get"
      # Window 2 receives the following (immediately):
      # /noise/Volume fff 0.000000 0.000000 1.000000
This printout says there is one parameter whose OSC address path is '/noise/Volume' (case matters) and its current value is 0, minimum value is 0, and maximum value is 1. Let's set it to 0.1:
    > oscsend localhost 5510 /noise/Volume f 0.1
      # Nothing is echoed, so let's ask for the current value:

    > oscsend localhost 5510 /noise/Volume s "get"
      # /noise/Volume fff 0.100000 0.000000 1.000000
      ^C  # Stop the noise app so that the next example can use port 5510.
It worked! Notice the use of 'f' to indicate that a floating-point value follows. If we didn't type control-C (^C) to end the program, the next example would listen for OSC messages on UDP port 5513. This is fine, and both programs would work in parallel (both being connected to system output in JACK), but we will keep to one example at a time here.

Now let's make OSC JACK apps out of some more FAUST examples and exercise them:

In Window 1:

    > cd <faust>/examples/dynamic/
    > # Mac: 
    >   faust2jaqt -osc distortion.dsp
    >   open ./distortion.app
    > # Linux:
    >   faust2jack -osc distortion.dsp
    >   ./distortion

If Window 2 is still set up running oscdump as above, we see

    Faust s " OSC version 1.22 - 'CUBIC_NONLINEARITY_cubicnl' is running on UDP ports 5513, 5511, 5512, sending on localhost"


In Window 3:
    > oscsend localhost 5510 /\* s "hello"
      # /distortion siii "0.0.0.0" 5510 5511 5512

    > oscsend localhost 5510 /\* s "get"
      # /distortion//SINE_WAVE_OSCILLATOR_oscrs//Amplitude fff -38.299999 -120.000000 10.000000
      # /distortion//SINE_WAVE_OSCILLATOR_oscrs//Frequency fff 37.599998 1.000000 88.000000
      # /distortion//SINE_WAVE_OSCILLATOR_oscrs//Portamento fff 0.846000 0.000000 1.000000
      # /distortion//CUBIC_NONLINEARITY_cubicnl//Bypass fff 0.000000 0.000000 1.000000
      # /distortion//CUBIC_NONLINEARITY_cubicnl//Drive fff 0.630000 0.000000 1.000000
      # /distortion//CUBIC_NONLINEARITY_cubicnl//Offset fff 0.000000 0.000000 1.000000
      # /distortion//SPECTRUM_ANALYZER_CONTROLS/Level_Averaging_Time fff 0.510000 0.000000 1.000000
      # /distortion//SPECTRUM_ANALYZER_CONTROLS/Level_dB_Offset fff 18.000000 0.000000 100.000000

    > oscsend localhost 5510 /distortion//CUBIC_NONLINEARITY_cubicnl//Drive f 0.9

    > oscsend localhost 5510 /distortion//CUBIC_NONLINEARITY_cubicnl//Drive s "get"
      # /distortion//CUBIC_NONLINEARITY_cubicnl//Drive fff 0.900000 0.000000 1.000000
and so on. Notice how the GUI grouping gets into the control name path. The appearance of // in the path indicates an unnamed group, which causes no problem. An attempt to set a parameter out of range (less than 0 or greater than 1 in this case) results in the parameter being clipped to the limit.

Here's another example (you now know which window is being listed):

      ^C
    > cd <faust>/examples/reverb/
    > # Mac: 
    >   faust2jaqt -osc zitaRev.dsp
    >   open ./zitaRev.app
    > # Linux:
    >   faust2jack -osc zitaRev.dsp
    >   ./zitaRev
      # Faust OSC version ssssiii "0.91" "-" "'Zita_Rev1'" "is running on UDP ports " 5510 5511 5512

    > oscsend localhost 5510 /\* s "get"
      # /Zita_Rev1/Input/In_Delay fff 24.400000 20.000000 100.000000
      # /Zita_Rev1/Decay_Times_in_Bands_(see_tooltips)/LF_X fff 1000.000000 50.000000 1000.000000
      # /Zita_Rev1/Decay_Times_in_Bands_(see_tooltips)/Low_RT60 fff 1.875000 1.000000 8.000000
      # /Zita_Rev1/Decay_Times_in_Bands_(see_tooltips)/Mid_RT60 fff 1.455000 1.000000 8.000000
      # /Zita_Rev1/Decay_Times_in_Bands_(see_tooltips)/HF_Damping fff 10418.099609 1500.000000 23520.000000
      # /Zita_Rev1/RM_Peaking_Equalizer_1/Eq1_Freq fff 1108.900024 40.000000 2500.000000
      # /Zita_Rev1/RM_Peaking_Equalizer_1/Eq1_Level fff 11.000000 -15.000000 15.000000
      # /Zita_Rev1/RM_Peaking_Equalizer_2/Eq2_Freq fff 2474.000000 40.000000 2500.000000
      # /Zita_Rev1/RM_Peaking_Equalizer_2/Eq2_Level fff -0.200000 -15.000000 15.000000
      # /Zita_Rev1/Output/Dry_Wet_Mix fff 1.000000 -1.000000 1.000000
      # /Zita_Rev1/Output/Level fff 14.150000 -70.000000 40.000000
Other examples are similar.

Finally, let's make an OSC JACK app out of the Faust-STK piano and try it out:

    > cd <faust>/examples/physicalModeling/faust-stk/
    > # Mac: 
    >   faust2jaqt -osc piano.dsp
    >   open ./piano.app
    > # Linux:
    >   faust2jack -osc piano.dsp
    >   ./piano
    # Faust OSC version ssssiii "0.91" "-" "'piano'" "is running on UDP ports " 5510 5511 5512

    > oscsend localhost 5510 /\* s "get"
      # /piano/Basic_Parameters/freq fff 440.000000 20.000000 20000.000000
      # /piano/Basic_Parameters/gain fff 1.000000 0.000000 1.000000
      # /piano/Basic_Parameters/gate fff 0.000000 0.000000 1.000000
      # /piano/Physical_Parameters/Brightness_Factor fff 0.000000 0.000000 1.000000
      # /piano/Physical_Parameters/Detuning_Factor fff 0.100000 0.000000 1.000000
      # /piano/Physical_Parameters/Hammer_Hardness fff 0.100000 0.000000 1.000000
      # /piano/Physical_Parameters/Stiffness_Factor fff 0.280000 0.000000 1.000000
      # /piano/Reverb/reverbGain fff 0.137000 0.000000 1.000000
      # /piano/Reverb/roomSize fff 0.720000 0.010000 2.000000
      # /piano/Spat/pan_angle fff 0.600000 0.000000 1.000000
      # /piano/Spat/spatial_width fff 0.500000 0.000000 1.000000
As with all synth examples, a note is played on the piano patch by setting parameters as desired (such as freq) and then setting the gate parameter to 1 to start the note. Setting gate back to 0 starts the decay phase of the note. In patches with ADSR or ASR envelopes, gate transitioning to 1 starts the Attack phase, while a transition to 0 starts the Release phase, as is typical in synthesizers driven by a keyboard. The bowed instrument is an example using an ADSR envelope:
      ^C
    > # (Make bowed like piano above)
    > ./bowed
      # Faust OSC version 0.91 application 'bowed' is running on UDP ports 5510, 5511, 5512

    > oscsend localhost 5510 /\* s "get"
      # /bowed/Basic_Parameters/freq fff 440.000000 20.000000 20000.000000
      # /bowed/Basic_Parameters/gain fff 1.000000 0.000000 1.000000
      # /bowed/Basic_Parameters/gate fff 0.000000 0.000000 1.000000
      # /bowed/Envelopes_and_Vibrato/Envelope_Parameters/Envelope_Attack fff 0.010000 0.000000 2.000000
      # /bowed/Envelopes_and_Vibrato/Envelope_Parameters/Envelope_Decay fff 0.050000 0.000000 2.000000
      # /bowed/Envelopes_and_Vibrato/Envelope_Parameters/Envelope_Release fff 0.100000 0.000000 2.000000
      # /bowed/Envelopes_and_Vibrato/Vibrato_Parameters/Vibrato_Attack fff 0.500000 0.000000 2.000000
      # /bowed/Envelopes_and_Vibrato/Vibrato_Parameters/Vibrato_Begin fff 0.050000 0.000000 2.000000
      # /bowed/Envelopes_and_Vibrato/Vibrato_Parameters/Vibrato_Freq fff 6.000000 1.000000 15.000000
      # /bowed/Envelopes_and_Vibrato/Vibrato_Parameters/Vibrato_Gain fff 0.010000 0.000000 1.000000
      # /bowed/Envelopes_and_Vibrato/Vibrato_Parameters/Vibrato_Release fff 0.010000 0.000000 2.000000
      # /bowed/Physical_and_Nonlinearity/Nonlinear_Filter_Parameters/Modulation_Frequency fff 220.000000 20.000000 1000.000000
      # /bowed/Physical_and_Nonlinearity/Nonlinear_Filter_Parameters/Modulation_Type fff 0.000000 0.000000 4.000000
      # /bowed/Physical_and_Nonlinearity/Nonlinear_Filter_Parameters/Nonlinearity fff 0.000000 0.000000 1.000000
      # /bowed/Physical_and_Nonlinearity/Nonlinear_Filter_Parameters/Nonlinearity_Attack fff 0.100000 0.000000 2.000000
      # /bowed/Physical_and_Nonlinearity/Physical_Parameters/Bow_Position fff 0.700000 0.010000 1.000000
      # /bowed/Physical_and_Nonlinearity/Physical_Parameters/Bow_Pressure fff 0.750000 0.000000 1.000000
      # /bowed/Reverb/reverbGain fff 0.137000 0.000000 1.000000
      # /bowed/Reverb/roomSize fff 0.720000 0.010000 2.000000
      # /bowed/Spat/pan_angle fff 0.600000 0.000000 1.000000
      # /bowed/Spat/spatial_width fff 0.500000 0.000000 1.000000
There are many more examples and Faust-STK examples to look into. This is just a start.



OSC Aliases

See the FAUST OSC documentation (Section 6.8) in the FAUST Quick Reference, for more advanced techniques such as the use of OSC aliases which allow arbitrary OSC messages25 to be mapped to controller parameters (for use with remote controllers such as TouchOSC on Android that can only transmit predefined messages).

The FAUST OSC documentation provides additional information.


Next  |  Prev  |  Top  |  JOS Index  |  JOS Pubs  |  JOS Home  |  Search

Download aspf.pdf
[Comment on this page via email]

``Audio Signal Processing in Faust'', by Julius O. Smith III
Copyright © 2023-08-16 by Julius O. Smith III
Center for Computer Research in Music and Acoustics (CCRMA),   Stanford University
CCRMA