=Paper=
{{Paper
|id=Vol-3893/Paper04.pdf
|storemode=property
|title=Phausto: fast and accessible DSP programming for sound and music creation in Pharo
|pdfUrl=https://ceur-ws.org/Vol-3893/Paper04.pdf
|volume=Vol-3893
|authors=Domenico Cipriani,Nahuel Palumbo,Sebastian Jordan Montaño,Stéphane Ducasse
|dblpUrl=https://dblp.org/rec/conf/iwst/CiprianiPJD24
}}
==Phausto: fast and accessible DSP programming for sound and music creation in Pharo==
Phausto: fast and accessible DSP programming for sound
and music creation in Pharo
Domenico Cipriani1 , Nahuel Palumbo2 , Sebastian Jordan Montaño2 and Stéphane Ducasse2
1
Pharo Association
2
Univ. Lille, Inria, CNRS, Centrale Lille, UMR 9189 CRIStAL, Park Plaza, Parc scientifique de la Haute-Borne, 40 Av. Halley Bât A,
59650 Villeneuve-d’Ascq, France
Abstract
This paper introduces Phausto, a library that generates sounds in Pharo programming language using Faust
(Functional Audio Streams), a programming language designed to develop real-time digital signal processors
(DSP).
In Phausto, DSP programs are created by the composition of Unit Generators written in a MUSIC-N style, like
the ChucK programming language, or from a string containing a valid Faust program.
We present Phausto’s API, implementation details and an overview of its syntax, and of Unit Generators and
ToolKit elements. We also analyze the motivations behind the project and identify its target audiences. Finally,
we present the conclusions drawn after one year of development and use, and outline the agenda for future work.
Keywords
sound synthesis, live coding, audio, DSP programming, Pharo, Faust, ChucK
1. Introduction
We present Phausto: a sound generation library for the Pharo programming language. Phausto is a
library created with the primary goal of integrating state-of-the-art sound synthesis inside the Pharo
ecosystem, allowed by a dynamic engine (Section 4). This engine connects a Faust [1] (Functional
Audio Streams) program generated to an underlying PortAudio [2] layer that, in turn connect with the
platform-specific low-level audio API. Together with these emerging sonic capabilities comes a new
quest: a transparent and effective API to develop and design Digital Signal Processors (DSP) such as
synthesisers and effects, both to be used in Pharo applications and for creative musical composition.
The Phausto API (Section 5) is designed to be modern and straightforward: its semantics and the
subdivision of Faust’s standard library functions into Phausto Unit Generators subclasses is inspired by
the ChucK [3] programming language, which takes this concept from MUSIC-N style programming
music languages [4]. Unit Generators (UGens) are basic building blocks for signal processing algorithms
that were first developed by Max Mathews and Joan E. Miller for the Music III program [5] in 1960.
UGens include processing modules such as oscillators, filters, envelopes and effects that can be connected
to create synthesis instruments (sometimes referred as patches).
DSP can be created in Phausto from a string containing a valid Faust program, as in:
dsp := DSP create: ’import("stdFaust.lib");
process = pm.marimba(400 ,3 ,7000 ,0.25 , 0.5 , ba.pulse(20000)) + pm.marimba
(800, 3 ,7000 ,0.25 , 0.5 , ba.pulse(10000));’
or by connecting Unit Generators using the Pharo basic syntax:
dsp := ((Marimba new freq: 800; trigger: (Pulse new period: 0.2) ) +
(Djembe new freq: 800; trigger: (Pulse new period: 0.1) )) asDsp.
IWST 2024: International Workshop on Smalltalk Technologies, July 9–11, 2024, Lille, France
$ mspgate@gmail.com (D. Cipriani); nahuel.palumbo@inria.fr (N. Palumbo); sebastian.jordan@inria.fr (S. Jordan
Montaño); stephane.ducasse@inria.fr (S. Ducasse)
0009-0005-3023-3192 (D. Cipriani)
© 2024 Copyright for this paper by its authors. Use permitted under Creative Commons License Attribution 4.0 International (CC BY 4.0).
CEUR
ceur-ws.org
Workshop ISSN 1613-0073
Proceedings
All Unit Generators have default values for their parameters, which are themself Faust boxes, too.
The main contributions of this paper are:
• A description of the Phausto library architecture and implementation details.
• Examples of sound synthesis using Phausto API.
• An overview of the Phausto Standard Library and ToolKit.
2. Motivation
We develop Phausto to generate sound directly from the Pharo environment, without needing external
dependencies to play performance during live coding sessions.
We have identified three primary target audiences for Phausto:
1. Pharo programmers who want to include sounds or sonic interaction in their Pharo applications,
including procedural audio designed Faust extensive physical modelling synthesis library;
2. Artists with little or no computer literacy who want to design and develop synthesisers and
effects for their music creation fast and easily. Pharo offers a transparent syntax with a neat IDE
and a browser that enables users to avoid complex library management; Phausto ensures all Faust
libraries are readily accessible as well-documented classes and methods.
3. Students and beginners who want to develop their audio plug-ins, by exporting DSPs developed
in Pharo to Cmajor1 patches thanks to the Faust2CMajor export2 . Cmajor is a new C-family
programming language for writing fast and portable audio software, created by Julian Storer
and Cesare Ferrari. Cmajor patches can be exported as native VST/AU/AAX plugins or loaded
directly into a Digital Audio Workstation (DAW) with the Cmajor VST/AU plugin
3. Phausto Overview and Architecture
ft
le
create a Box from
ne to
BOX creates a DSP from a Box
an dio
Phausto Objects
l
ch au
API
ts
pu
the FAUST generated
t
ou
prorgam computes
creates DSP DYNAMIC ENGINE samples for the
fills blocks of
underlying audio layer PLATFORM
from a String audio bufffers
PHAUSTO PORTAUDIO SPECIFIC
LIBFAUST AUDIO DRIVER
ou
t
Unit Generators are
pu c
ts ha
implemented
au nn
in the FAUST libraries
di el
o
to
rig
FAUST LIBRARIES
ht
(stdfaust.lib)
Figure 1: Overview of Phausto library and the embedded Faust dynamic engine.
Phausto is an open-source Pharo library to create synthesisers and audio effects that are converted
into Faust programs by an embedded Faust compiler. Figure 1 shows an overview of its architecture.
1
https://cmajor.dev/
2
https://github.com/grame-cncm/Faust/tree/master-dev/architecture/cmajor#Faust2cmajor
The Dynamic Engine in the backend initialises the PortAudio library and opens a stream for audio
I/O. It creates a DSP from strings of valid Faust codes or Boxes created with the Phausto API. The
definitions of the Unit Generators are implemented in the Faust libraries, which are accessed by the
Dynamic Engine when DSPs are created.
The DSP is a Faust program that computes floating point numbers between -1.0 and 1.0 as output.
These values fill the blocks of a PortAudio stream. The platform-specific audio driver transforms the
PortAudio stream into sound, using the sound interface Digital-To-Analog converter.
4. Under-the-hood: Faust programming language
Faust (Functional Audio Stream) [1] is a functional programming language tailored to sound synthesis
and audio processing created at the GRAME-CNCM Research Department3 . It provides developers
with an alternative to C/C++ for designing and deploying DSPs. One of its key features is a block
diagram-oriented syntax, which eases a modular approach to the creation of synthesisers and effects. A
Faust program describes a signal processor, essentially mapping input signals to output signals, but it
does not outline a connection to the external world4 .
4.1. Faust dynamic engine
The dynamic engine implementation describes a straightforward C API for Faust objects including
the audio drivers responsible for rendering the samples computed by the DSP and the library used for
reading audio data files. Faust DSP objects are structures that can be either instantiated from a string of
valid Faust code by calling the createDsp function:
dsp* createDsp (const char* name_app, const char* dsp_content,
int argc, const char* argv[], const char* target, int opt_level);
or from Boxes (Section 4.3) with the createDspFromBoxes function:
dsp* createDspFromBoxes(const char* name_app, Box box,
int argc, const char* argv[], const char* target, int opt_level);
After being created, DSP needs to be initialized by calling the initDSP function with a sampling
rate and buffer size for the audio driver. 5 . Finally, start function is called to open the audio stream
and processing audio blocks until stop function is called.
bool initDsp(dsp* dsp, RendererType renderer, int sr, int bsize);
bool startDsp(dsp* dsp);
The dynamic engine also allows access to and modification of DSP parameters using the
getParamValueDsp and setParamValueDsp functions:
FaustFLOAT getParamValueDsp (dsp* dsp_ext, int p);
FaustFLOAT setParamValueDsp (dsp* dsp_ext, int p, FaustFLOAT val);
The dynamic engine includes the Faust Compiler [7], libFaust in Figure 1. The compiler generates
bytecode from the Faust Imperative Representation, which is then successively executed by a stack-
based virtual machine. We chose this approach for its lightweight nature and zero dependencies,
although other options with faster execution, as an LLVM [8] backend6 . The Faust compiler meets the
3
https://Faust.grame.fr/
4
https://Faustdoc.grame.fr/manual/architectures/
5
For a more detailed description of sampling rates, audio buffer size and audio drivers, refer to the first chapters of The Audio
Programming Book [6]
6
Linked with components of the LLVM compiler toolchain, the library allows the deployment of a complete dynamic
compilation chain from source to executable code.
performance needs of Phausto intended goals and audience; as interactions with the Faust program
occur only once it has been created and initialized, the choice between the LLLVM compiler and the
backend interpreter does not affect the control on-the-fly of the DSP parameters.
4.2. The PortAudio layer
To maintain compatibility across different operating systems and keep the ToolKit as lightweight as
possible, we leverage PortAudio. PortAudio is an Open Source Cross Platform C library7 and API for
audio input and output [2]. It was designed to simplify the development of real-time audio applications,
and it is part of a larger initiative called PortMusic8 that also includes MIDI9 capabilities.
PortAudio renders the samples computed by the Faust interpreter with the PortAudio and Faust’s
native library10 . This approach ensures all the dependencies (including all Faust libraries) to be less
than 10 MB.
PortAudio handles the connection with the audio input and audio ports on the host platform. It
internally manages audio stream buffers and requests audio processing from the client application via a
callback that is associated with an opened stream. In the dynamic engine, this association is managed
by the following function:
bool initDsp(dsp* dsp, RendererType renderer, int sr, int bsize);
For instance, in Phausto we initialise a DSP by calling:
initDsp(aDSP, 0, 44100, 512);
This function sets the sampling rate and the buffer size and allows one to choose a different renderer
from PortAudio if needed.
4.3. The Box API
The Faust C box API11 allows for the programmatic creation of a box expression, which is used to create
a DSP object. This stage is an intermediate public entry point created in the Semantic Phase of Faust’s
compilation chain. The Semantic Phase is the first step of Faust’s compilation chain; starting from the
DSP source code written in Faust, the Semantic Phase produces signals that are (conceptually) infinite
streams of samples. Boxes can be created by calling a specific function defined in libFaust-box-c. e.g., for
creating a UI button:
Box CboxButton(const char* label);
Or from a string of Faust code by calling:
Box CDSPToBoxes(const char* name_app, const char* dsp_content,
int argc, const char* argv[], int* inputs, int* outputs, char* error_msg);
The Box API also supplies methods to convert numbers into Boxes and to connect Boxes via the five
binary composition operators of the language12
7
https://github.com/PortAudio/portaudio
8
https://www.cs.cmu.edu/~music/portmusic/
9
https://midi.org/
10
https://github.com/grame-cncm/Faust/blob/master-dev/architecture/Faust/gui/Soundfile.h
11
https://Faustdoc.grame.fr/tutorials/box-api/
12
In Faust there are five binary composition operations to combine block diagrams: sequential( :) , parallel( , ) , split( <: )
merge ( :>) , recursive ( ~ ) . For a detailed description of Faust binary operators see [1].
5. Phausto programming by example: Fast and easy sound synthesis
Programming DSP with Phausto is fast and easy because it combines the modular synthesiser [9]
creative and flexible mindset with the Pharo Object Oriented Programming paradigm. Phausto takes
advantage of Pharo’s concise and iconic syntax, the reflectiveness of the environment, and the ease of
developing reusable code. With Phausto, Pharo becomes a fully-fledged IDE for audio synthesis and
algorithmic composition without needing additional extensions (in contrast to other IDEs and code
editors in mainstream programming languages). Moreover, manipulating the DSP parameters using
Pharo syntax provides musicians with a tool offering unnoticeable latency13 for their live performances
and compositions.
5.1. Start your engine
pulse := PulseOsc new. "Instantiate an Unit Generator"
dsp := pulse stereo asDsp. "Create the DSP in stereo mode"
dsp init. "Initialize the DSP"
dsp start. "Start the sound"
dsp stop. "Stop the sound"
dsp destroy. "Destroy the DSP"
Listing 1: Simple example using Phausto
Listing 1 shows a simple example using Phausto playing a Pulse Oscillator. First, we instantiate the
UGen to play, in this case, a Pulse Oscillator. Then we create a stereo DSP by sending the messages
asDSP to our Pulse Oscillator. (To change the mono output of a synth to stereo, we send the stereo
message to the Box that is the result of the multiplication).
Once our DSP is created, we initialize and start it to hear the sound it generates. We can stop the
DSP whenever we want. If we are finished with our DSP programming, it would be a good practice to
destroy it.
5.2. Taking Control of Configuration and Parameters
Each UGen has different configuration parameters with default values, each of them documented in the
class comments. For example, to control the parameters of a Pulse Oscillator we need to specify the
freq - for frequency in Hertz, and duty - to change the oscillator duty cycle (between 0 and 1).
pulse := PulseOsc new freq: 220; duty: (LFOTriPos new freq: 4).
dsp := pulse stereo asDsp.
dsp init.
dsp start.
Listing 2: Configuring UGen parameters
13
The latency time refers to the duration required to execute the message setValue:parameter: (which is is an FFI call),
to execute. If we run a simple benchmark:
[1000 timesRepeat: [dsp setValue: (Random new nextIntegerBetween: 90 and: 900) parameter:
’SquareOscFreq’ ]] timeToRun.
The results show that a single call takes approximately 0.007 milliseconds. At a 192 kHz sample rate, this latency is slightly
more than 1 sample, making it effectively instantaneous compared to the rate at which the computer can generate sound.
However, it’s important to consider that the latency of calling the function void setParamValueDsp(dsp* dsp_ext,
int p, FaustFLOAT val); through the dynamic engine primarily depends on the buffer size and sample rate parameters
used in the Phausto audio layer. By default, Phausto initialize its DSPs with a 44100 sample rate and a buffer size of 512
samples. This corresponds to a latency of approximately 11.6 ms, which is below the 20 ms threshold generally considered
to be imperceptible or minimally disruptive for human perception, as demonstrated by the Haas effect.
The code in Listing 2 sets the frequency of the Pulse Oscillator to 220 Hz (default frequency is 440 Hz)
and assigns the value of the duty cycle to a Low-Frequency Oscillator (LFO) with a Triangular Positive
Waveform (LFOTriPos oscillates between 0 and 1).
5.3. Live programming
To modify a parameter of a UnitGenerator in real time, while the DSP is playing, we create a PhHSlider
by sending the message init: initialValue to a ByteSymbol. This creates a PhHSlider with
the ByteSymbol as a label and the required initial value. Then, we control the parameter on live by
sending the message setValue: parameter: to our DSP.
lfoFreq := #lfoFreq init: 2.
pulse := PulseOsc new freq: 220; duty: (LFOTriPos new freq: lfoFreq ).
dsp := pulse asDsp.
dsp init.
dsp start.
"Change the value of a parameter while the sound is playing"
dsp setValue: 8 parameter: ’lfoFreq’.
... "Continue using the DSP until the end"
Listing 3: Changing UGen parameters while playing
Listing 3 shows an example of changing the frequency of the LFO from 2 to 8 Hz after the DSP is
started.
5.4. Music composition with Pharo Processes
Once we have started our DSP we can create music compositions using Pharo Processes, Blocks and
Delays.
synth := (SquareOsc new freq: #SquareNote) * (AREnv new trigger: #SquareGate).
dsp := (synth => SatRev new) stereo asDsp.
dsp init.
dsp start.
note := 72.
time := 2.
[
24 timesRepeat: [
dsp playNote: note prefix: ’Square’ dur: 0.1.
time wait.
note := note + 1 .
time := time * 0.85 ]
] fork.
dsp stop.
dsp destroy.
Listing 4: Algorithmic music composition
For instance, code in Listing 4 plays a sequence of 24 chromatic notes starting from C5 (MIDI note
number 72) playing at exponentially shorter intervals of time.
In this example, we have created a Square Oscillator which has its frequency connected to a PhHSlider
(to be controlled), multiplied for an Attack-Release Envelope controlled by other PhHSlider.
The playNote:prefix:dur: method modifies two parameters:
• it converts a MIDI note number to a frequency in Hertz and sends this value to the SquareNote
parameter;
• it sends the value 1 and after 0.1 seconds a value of 0 to the parameter SquareGate.
Essentially, the playNote:prefix:dur: the method simulates the action of playing a key on a
MIDI keyboard. For this operation, our DSP needs a parameter with the gate suffix to trigger its envelope
and a parameter named Note for controlling the frequency. Both parameters must share the same prefix,
which is ’Square’ in this example.
6. Core Implementation
Phausto allows Pharo users to use functions and data structures from the Faust programming language
via Foreign Function Interface (FFI) [10]. The library contains the API to instantiate, access and modify
DSP and create Faust Boxes as described in Section 4.
To use Phausto, the librariesBundle folder must be downloaded from the GitHub repository and placed
next to the current Pharo image14 . The libraries bundle includes hundreds of functions for synthesis
and processing audio written in Faust (see Section 7).
6.1. DSP creation from Phausto Boxes
We create UnitGenerators objects in Phausto using the Faust Box API (described in Section 4.3). It
enables writing DSP in Pharo with a dedicated API that hides Faust syntax from the user.
The Box API class provides the connection to over 50 functions that we have considered fundamental
for developing the Phausto API. These functions include those to create Faust primitives, composition
operators and mathematical expressions. The methods that create or combine boxes return a new Box.
If the operation fails, a null pointer is returned.
6.2. The lifecycle of a DSP
A DSP object is originally initialised (i.e., connected to the PortAudio layer) and subsequently started,
stopped, and at the end of its use destroyed to avoid dangling pointers. All these methods call to the
corresponding function defined in the dynamic engine.
Once a DSP is initialised we can check its parameters on a Transcript (traceAllParams) and modify
the value of its parameters sending the message setValue: aParameter with a Number or a Box as
the first argument and with a String as the second argument.
6.3. Managing the global compilation context
To use the Faust Box API we create a singleton global compilation context before we create a Box, and
destroy this context after the Box has been used to create a DSP. For this reason, the Box class has a
shared variable called libContext not initialised when the Pharo image is opened. Every call to the
BoxAPI class in Phausto first ensures the creation of the context by calling createLibContextFFI if
not exist. At the same time, every time a DSP is created, the compilation context is destroyed by calling
BoxAPI unique instance destroyLibContext.
7. Phausto Standard Library and the ToolKit
The Phausto Standard Library includes the bindings to functions in the standard Faust library stdFaust.lib
15 . They are implemented as subclasses of UnitGenerator and organised in package tags, while the
ma.lib (which includes mathematical operations) is ported as methods of the PhBox superclass.
14
https://github.com/lucretiomsp/phausto
15
https://faustlibraries.grame.fr/
The design of the Phausto API exposes all original arguments as instance variables of the UGen
object and default values are set during initialisation16 . The setters convert their arguments into a Box,
allowing the user to use both, fixed numbers or other boxes (e.g., other UnitGenerators, or a UIPrimitive
to control the variable in real-time).
One specific UnitGenerator is created by sending the asBox message. This method first creates an
intermediateBox from a Faust code string without parameters and returns a finalBox from the connection
of the instance variables to the intermediateBox. Listing 5 presents the binding between the djembe
function in Faust and the Djembe class in Phausto.
"djembe function in physmodels.lib"
pm.djembe(freq, strikePosition, strikeSharpness, gain, trigger) : _
"Djembe class Phausto"
Djembe >>> initialize
super initialize.
processExpression := ’process = pm.djembe;’.
self freq: 440.
self strikePosition: 0.5.
self strikeSharpness: 0.8.
self gain: 0.5.
self trigger: 0.0
Djembe >>> asBox
| intermediateBox finalBox |
intermediateBox := super asBox.
finalBox := (freq , strikePosition , strikeSharpness , gain , trigger )
connectTo: intermediateBox.
^ finalBox
Listing 5: Pharo Djembe binding
The ToolKit17 tag of the Phausto package includes a set of classes that do not have a corresponding
function in the standard Faust library. These classes encompass units for sound generations that
combine one or more UnitGenerators.
The ToolKit includes a combination of effects and modulators (e.g., FIlterEnvelope or FilterLFO),
effects and synthesizers with a custom design (e.g., DelayFeedBack or SamplePlayer) or ‘utilities’ as the
Incrementer (that increments its output by an increment value at every step).
8. Related work
One of the primary sources of inspiration for Phausto is Kyma [12], an object-oriented environment for
music composition written in Smalltalk-80, created by Carla Scaletti in the mid of 1980. The first version
of Kyma ran on a Macintosh 512k computer and could not manipulate sound in real time. This is why
Scaletti and Kurt J. Hebel collaborated to integrate a separate multiprocessor to compute and process
audio [13]. Although there is no direct connection between Phausto and Kyma, we share Scaletti’s
desire to make music programming more accessible to composers without a strong background in
computer science. Our goal is also to make music creation more accessible to programmers without a
strong background in music and sound synthesis.
Pharo programmers could play sound samples in Pharo since Pharo 9.0 using the Sound package18 .
16
The default values have been an arbitrary choice, influenced by other programming languages such as ChucK, PureData,
SuperCollider, as well as our direct experience and by empirical audio tests during development.
17
The ToolKit name is a homage to the Synthesis ToolKit [11] in C++(STK)by Perry R. Cook and Gary Scavone, as its primary
goal is to facilitate faster development of synthesisers and effects.
18
https://github.com/pharo-contributions/Sound
Pharo Sound plays samples and sounds by FFI calls to the SDL2 library19 . This package is poorly
documented and offers very few audio generators and effects based on a Pharo implementation of
low-level C techniques for computing samples. Consequently, its API is difficult to access and complex
to expand, it does not use terminology consistent with modern audio programming practices.
FaustPy20 is a Python wrapper for Faust implemented using CFFI that works with Python 2.7 and
3.2+. It is the only wrapper for a high-level general-purpose programming language supporting object-
oriented programming.
9. Future Work
In its first year of development, Phausto has become a cross-platform stable library and we have been
able to provide bindings to more of the 30% of the Faust Box API. Additionally, 25% of the functions of
the Faust standard library has been implemented as classes and tested. In the following months, our
focus will be on porting all the functionalities of the Faust programming language. This includes the
ability to visualize the DSP block diagram as a .svg file and the possibility to save DSP written in Pharo
as a file, which can be exported to different target languages, such as CMajor, C++ and WAST21 .
Along with the implementation of all the UnitGenerators, the new ToolKit classes will be designed
and implemented to meet the needs of musician and sonic artists. As Phausto expands, more effort will
be required to prepare valid tests for all the UnitGenerators, which include an inquiry into how to write
valid tests for audio generators.
In addition, we have planned to develop a new package called TurboPhausto is specifically designed
to program music on the fly with Coypu. TurboPhausto is inspired by the SuperDirt engine for
SuperCollider. It provides a set of ready-to-use synthesizers and effects and an API to easily play a
collection of audio samples located in subfolders of a specific folder. We will include a substantial
amount of high-quality samples for instant gratification and the option to expand the collection.
Finally, in collaboration with the Evref team, we are working on a live programming development
environment. It encompasses a custom Playground and a set of custom UI elements (faders, rotary
sliders, buttons, and more) for Phausto made with Toplo22 .
10. Conclusion
After ten months of development, Phausto is a comprehensive solution for enabling sound synthesis
into Pharo applications. Phausto offers a diverse ToolKit that includes sample players, basic oscillators,
envelopes, various physical models, resonant filters, reverbs, and delays. The extensive list of Unit
Generators features a streamlined API for parameter manipulation.
Additionally, TurboPhausto’s synthesizers and effects were showcased in a 30-minute live perfor-
mance titled "Riding the MoofLod" during the ESUG2024 conference at Lille.
Acknowledgments
We would like to thank Stephane Sletz, Yann Orlarey, Guillermo Polito, Esteban Lorenzano and Pablo
Tesone, for their invaluable support, push and assistance throughout the development of Phausto.
We express our gratitude to the organisation of the ESUG for the inspiration and the knowledge we
gained during the conferences. In particular, the meetings with the members of the Pharo team and
GRAME in Lyon 2023. It was instrumental in the birth of Phausto.
19
SimpleDirectMedia is a cross-platform development library designed to provide low-level access to audio, keyboard, mouse
and graphics hardware.
20
https://github.com/marcecj/Faust_python
21
https://webassembly.js.org/docs/contrib-wat-vs-wast.html
22
https://github.com/pharo-graphics/Toplo
Special thanks to Carla Scaletti and Kurt J. Hebel at Symbolic Sound Corporation fo their lifelong
effort to spread love for Smalltalk and computer music, and to Cristian Vogel for pushing Kyma into the
world of electronic dance music.
This work has been supported by the Pharo Consortium.
References
[1] E. Gaudrain, Y. Orlarey, A FAUST Tutorial, 2003. URL: https://hal.science/hal-02158895, manual.
[2] R. Bencina, P. Burk, Portaudio-an open source cross platform audio api, in: ICMC, 2001.
[3] G. Wang, P. Cook, Chuck: A concurrent, on-the-fly audio programming language, 2003.
[4] G. Wang, The chuck audio programming language. "a strongly-timed and on-the-fly environ/men-
tality", Ph.D. thesis, USA, 2008. AAI3323202.
[5] C. Roads, The Computer Music Tutorial, MIT Press, Cambridge, MA, USA, 1996.
[6] R. Boulanger, V. Lazzarini, The Audio Programming Book, The MIT Press, 2010.
[7] S. Letz, Y. Orlarey, D. Fober, An Overview of the FAUST Developer Ecosystem, in: International
Faust Conference, Mainz, Germany, 2018. URL: https://hal.science/hal-02158929.
[8] C. Lattner, V. Adve, Llvm: a compilation framework for lifelong program analysis and transforma-
tion, in: International Symposium on Code Generation and Optimization, 2004. CGO 2004., 2004,
pp. 75–86. doi:10.1109/CGO.2004.1281665.
[9] M. Vail, The synthesizer: a comprehensive guide to understanding, programming, playing, and
recording the ultimate electronic music instrument, Oxford University Press, 2014.
[10] G. Polito, S. Ducasse, P. Tesone, T. Brunzie, Unified ffi - calling foreign functions from pharo, 2020.
URL: http://books.pharo.org/booklet-uffi/.
[11] P. R. Cook, G. P. Scavone, The synthesis toolkit (stk), 1999.
[12] C. Scaletti, Composing sound objects in kyma, Perspectives of New Music (1989) 42–69.
[13] M. Heying, A Complex and Interactive Network: Carla Scaletti, the Kyma System, and the Kyma
User Community, University of California, Santa Cruz, 2019.