A patch built in a Playground does not have to stay there. Phausto can emit a CMajor patch, a complete JUCE plugin project, or C++ for a Bela board — from the same object you have been listening to.

1. Why export at all

Pharo is an excellent place to design a sound and a poor place to ship one. Exporting closes that gap: the instrument you prototyped interactively becomes a plugin your collaborators can load, or a binary on a board that boots without a computer attached.

Everything rests on the same fact — a Phausto patch is a FAUST program. The exporters take the FAUST that generatedCode would give you and wrap it in whatever scaffolding the target needs.

Export is a code generator, not a compiler Phausto writes source files. Building them is a separate step with the target's own toolchain — the CMajor runtime, JUCE and CMake, or the Bela toolchain.

2. Plain FAUST files

The simplest export is the FAUST source itself, which is also the most portable — anything that accepts FAUST will take it.

MessageWrites
createFileNamed: aStringThe DSP as a FAUST file
createFaustSynthFileNamed: aNameA synth-shaped FAUST file
createFaustPolySynthFileNamed: aNameA polyphonic synth file
createFaustSynthHeaderFileNamed: aNameThe accompanying header
createFaustHeaderFileNamed: aName for: aPluginTypeA header for a given plugin type
generatedCodeThe source as a string, without writing anything
writeAsPosixText: aString to: aFileReferenceWrite text with POSIX line endings
synth := SawOsc new => ADSREnv new => MoogVcf new.
dsp := synth stereo asDsp.
dsp init.

dsp generatedCode.                        "inspect it first"
dsp createFaustSynthFileNamed: 'MySynth'.

3. CMajor patches

CMajor is a language and runtime for audio, with its own patch format that loads in a host or standalone player. Phausto emits complete patches, including the interface.

MessageProduces
createCmajorPatchNamed: aNameAn instrument patch
createCmajorFXPatchNamed: aNameAn effect patch — audio in, audio out
createCmajorMIDIPatchNamed: aNameA MIDI-driven instrument patch
dsp createCmajorMIDIPatchNamed: 'MyInstrument'.

3.1 The CMajor classes

The export is modelled by objects rather than string templating, so it can be extended:

ClassRole
CmajorPatchA patch
CmajorFXPatchAn effect patch
CmajorMIDIPatchA MIDI instrument patch
CmajorViewThe patch's interface
CmajorUIElementSuperclass of the view elements
CmajorKnobA knob
CmajorFaderA fader
CmajorBackgroundThe view background

Your UI primitives become CMajor endpoints and view elements automatically — a PhHSlider in the patch becomes a control in the exported interface, with the range you declared.

3.2 Polyphonic wrapping

A Phausto patch is monophonic by construction. To make a CMajor instrument polyphonic it has to be wrapped in a voice allocator, and Phausto generates that wrapper:

MessageProduces
asCmajorPolyWrapperFor: aNameA polyphonic voice wrapper
aDictionary asCmajorPolyWrapperThe wrapper from an endpoint description
aDictionary asCmajorEventEndpointAn event endpoint
aDictionary asCmajorEventsToVoicesConnectionEvent-to-voice routing
aDictionary asCmajorListOfUIEndpointsThe UI endpoint list
Design for one voice Build and tune the instrument as a single voice. Polyphony is added at export, and a patch that sounds right monophonically will almost always sound right multiplied.

4. JUCE plugins

The most substantial exporter generates a complete JUCE project — processor, editor, parameter tree and build files — ready to compile into a VST3 or Audio Unit.

MessageProduces
export2JuceWithName: aString type: aPluginTypeA JUCE project
export2JuceAPVTSWithName: aString type: aPluginTypeA project with a full parameter tree
export2JuceAPVTSWithName: aString for: aPluginTypeThe same, alternative form
dsp export2JuceAPVTSWithName: 'MyPlugin' type: aPluginType.

4.1 Plugin types

The plugin type selects which project template is used. Phausto ships three, corresponding to the three shapes a plugin can take:

TemplateShape
Mono synthMIDI in, audio out, one voice
Poly synthMIDI in, audio out, multiple voices
EffectsAudio in, audio out

The templates live in faus2JuceTemplates in the Phausto repository, as Source_monoSynth, Source_polySynth and Source_effects. Reading them is the quickest way to see what the exporter fills in.

4.2 APVTS: the parameter tree

JUCE's AudioProcessorValueTreeState is how a plugin exposes automatable parameters to a host. Phausto builds it from your patch's own controls, which is why declaring proper ranges on your widgets pays off at export time.

MessageReturns
apvtsControlsThe controls to expose
apvtsParameterControlsJust the automatable parameters
apvtsControlsFrom: aJsonStringControls parsed from a UI description
apvtsParameterControlsFrom: aJsonStringParameters from a UI description
apvtsDescriptorRowFor: aControlOne row of the parameter descriptor
This is what DSPParameter was for A parameter's label, range, step and default all travel into the plugin. The separation between DSPParameter and DSPParameterStore described in DSP & Parameter API §8 exists precisely so this mapping is straightforward.

4.3 The generated files

MessageWrites
createCppAPVTSFilesNamed:for:Processor source with APVTS
createHeaderAPVTSFilesNamed:for:Processor header
createCppEditorAPVTSFilesNamed:for:Editor source
createHeaderEditorAPVTSFilesNamed:for:Editor header
createPluginProcessorHeader:Plugin processor header
createPhaustoParamsHeaderNamed:A header of parameter definitions
createJucerFileNamed:for:A Projucer project file
createCMakeFileNamed:for:A CMake build file

Setter code for the C++ side is generated from your parameter names through the String and Array extensions — asCppSetterDefinition, asCppSetterImplementationFor: and their plural forms — so each Phausto parameter becomes a named C++ setter rather than a numeric index.

5. Bela

Bela is an embedded platform for low-latency audio. Exporting to it produces a C++ file to build on the board:

MessageWrites
createBelaCppFileNamed: aNameA Bela-ready C++ file

Bela's analogue inputs are reached through widget metadata: declaring belaPin: on a UI primitive binds that control to a physical input. A potentiometer wired to the board then drives the parameter directly, with no code in between.

"This slider becomes a hardware input on the board"
cutoff := PhHSlider new
  label: 'Cutoff' values: #(800 40 12000 1);
  belaPin: 0.
Prototype with the mouse, deploy to the knob The same declaration is a slider in Pharo and an analogue pin on the board. You can develop the instrument entirely on your laptop and only then move it, without changing the patch.

6. Writing a patch that travels

Some habits cost nothing while prototyping and save real trouble at export. All of them amount to the same principle: put information in the patch rather than in the Playground around it.

Use widgets, not numbers — a value fixed as a literal is invisible to every exporter. A PhHSlider becomes a plugin parameter, a CMajor endpoint or a Bela pin.
Declare real ranges — the minimum, maximum, step and default travel with the parameter and become what the host shows. Sloppy ranges become a sloppy plugin.
Name things deliberately — parameter names become the names musicians see. Relabel your UGens, as in Unit Generators §2.2.
Express time in seconds — a delay fixed in samples changes pitch at a different sample rate. Use PhSec2Samp or PhSampleRate; see Math §6.
Keep sequencing outside the patch — forked Pharo loops do not export. Rhythm that must survive belongs in the signal graph, as pulses and counters; see Sequencing §1.
Declare MIDI bindings on the widgetmidiCtrl: is honoured by the FAUST runtime, by the plugin and by the board alike.
The one that catches everyone A patch driven by [ ... ] fork and dsp setValue:parameter: makes sound in Pharo and silence everywhere else. Pharo is the sequencer in that arrangement, and Pharo does not come with the plugin.

7. Where to go next

DocumentWhat it covers
UI PrimitivesDeclaring the controls that become plugin parameters.
DSP & Parameter APIThe parameter model the exporters read.
Raw FAUST & the Box APIReading and shaping the FAUST that gets exported.
MIDI & Playing NotesMaking an instrument playable before you export it.

8. Troubleshooting

The exported plugin has no parameters

The patch was built with literal numbers, so there was nothing to expose. Use widgets — §6.

The plugin loads but is silent

If the sequencing lived in a forked Pharo loop, it did not come with you. Move the rhythm into the signal graph, or drive the plugin from the host — §6.

Parameter ranges in the host look wrong

They are whatever you declared on the widget. Check the values: array order — initial value first. See UI Primitives §2.1.

The exported instrument is monophonic

Phausto patches are single-voice by construction. Use a polyphonic template for JUCE, or the CMajor poly wrapper — §3.2 and §4.1.

The generated project will not build

Export writes source, not binaries — the target's toolchain does the rest. Confirm JUCE, CMake or the Bela toolchain is installed and that the template files are present — §1, §4.1.

The exported patch sounds different from the one in Pharo

Most often a sample-rate assumption. Anything specified in samples will shift; express times in seconds — §6.