
FAUST2PD
========

This package, which now comes bundled with the Faust distribution, contains
software which makes it easier to use Faust DSPs with Pd. It also includes a
bunch of examples. This software is distributed under the GPL; see the COPYING
file for details.

This software has only been tested on Linux so far, but there shouldn't be any
major roadblocks preventing it to work on other systems, as all required
software has been ported to various platforms including OSX and Windows.

Talking about requirements, you'll need GNU C++ and make, Pure Data a.k.a. Pd
(http://puredata.info) and, of course, Faust (http://faudiostream.sf.net).
Recent Faust versions (>0.9.8) should already include the puredata
architecture, otherwise you should copy the faust/puredata.cpp file into the
/usr/lib/faust directory where Faust's other architecture files are. If you
want to use the faust2pd program or try the Q sequencer example you'll also
need the Q interpreter (version 7.8 or later) available from
http://q-lang.sf.net. NB: On this site you can also find source and SUSE 10.1
RPMs for Faust and Pd (see the Dependencies section on the Download page).
Also, if you get a recent version of the "all-in-one" Q package then faust2pd
should already be included so that you do not have to install it separately.

QUICKSTART
==========

Run "make" to compile the Faust .dsp sources to corresponding Pd plugins.
After that you should be able to run the examples in the various
subdirectories of the examples directory. Everything is set up so that you can
try the examples "in-place", without installing anything except the required
software as noted above. You can also run "make realclean" before "make" to
regenerate everything from scratch (this requires the faust2pd script, so this
will only work if you already installed the Q interpreter).

Faust plugins work in much the same way as the well-known plugin~ object
(which interfaces to LADSPA plugins), except that each Faust DSP is compiled
to its own Pd external. Under Linux, the basic compilation process is as
follows (taking the freeverb module from the Faust distribution as an
example):

# compile the Faust source to a C++ module using the "puredata" architecture
faust -a puredata.cpp freeverb.dsp -o freeverb.cpp
# compile the C++ module to a Pd plugin
g++ -shared -Dmydsp=freeverb freeverb.cpp -o freeverb~.pd_linux

By these means, a Faust DSP named XYZ with N audio inputs and M audio outputs
becomes a Pd object XYZ~ with N+1 inlets and M+1 outlets. The leftmost
inlet/outlet pair is for control messages only. This allows you to inspect and
change the controls the unit provides, as detailed below. The remaining inlets
and outlets are the audio inputs and outputs of the unit, respectively. For
instance, "freeverb.dsp" becomes the Pd object "freeverb~" which, in addition
to the control inlet/outlet pair, has 2 audio inputs and outputs.

When creating a Faust object it is also possible to specify, as optional
creation parameters, an extra unit name (this is explained in the following
section) and a sample rate. If no sample rate is specified explicitly, it
defaults to the sample rate at which Pd is executing. (Usually it is not
necessary or even desirable to override the default choice, but this might
occasionally be useful for debugging purposes.)

In addition, there is also a Q script named "faust2pd", described in more
detail below, which allows you to create Pd abstractions as "wrappers" around
Faust units. The wrappers generated by faust2pd can be used in Pd patches just
like any other Pd objects. They are much easier to operate than the "naked"
Faust plugins themselves, as they also provide "graph-on-parent" GUI elements
to inspect and change the control values.

Note that, just as with other Pd externals and abstractions, the compiled
.pd_linux modules and wrapper patches must be put somewhere where Pd can find
them. To these ends you can either move the files into the directory with the
patches that use the plugin, or you can put them into the lib/pd/extra
directory or some other directory on Pd's library path for system-wide use.

CONTROL INTERFACE
======= =========

The control inlet of a Faust plugin understands messages in one of the
following forms:

- "bang", which reports all available controls of the unit on the control
  outlet, in the form `TYPE NAME VAL INIT MIN MAX STEP' where TYPE is the type
  of the control as specified in the Faust source (checkbox, nentry, etc.),
  NAME its (fully qualified) name, VAL the current value, and INIT, MIN,
  MAX, STEP the initial value, minimum, maximum and stepsize of the control,
  respectively.

- "foo 0.99", which sets the control "foo" to the value 0.99, and outputs
  nothing.

- Just "foo", which outputs the (fully qualified) name and current value of
  the "foo" control on the control outlet.

Control names can be specified in their fully qualified form, like e.g.
"/gnu/bar/foo" which indicates the control "foo" in the subgroup "bar" of the
topmost group "gnu", following the hierarchical group layout defined in the
Faust source. This lets you distinguish between different controls with the
same name which are located in different groups. To find out about all the
controls of a unit and their fully qualified names, you can bang the control
inlet of the unit as described above, and connect its control outlet to a
"print" object, which will cause the descriptions of all controls to be
printed in Pd's main window. (The same information can also be used, e.g., to
initialize GUI elements with the proper values. Patches generated with
faust2pd rely on this.)

You can also specify just a part of the control path (like "bar/foo" or just
"foo" in the example above) which means that the message applies to *all*
controls which have the given pathname as the final portion of their fully
qualified name. Thus, if there is more than one "foo" control in different
groups of the Faust unit then sending the message "foo" to the control inlet
will report the fully qualified name and value for each of them. Likewise,
sending "foo 0.99" will set the value of all controls named "foo" at once.

Concerning the naming of Faust controls in Pd you should also note the
following:

- A unit name can be specified at object creation time, in which case the
  given symbol is used as a prefix for all control names of the unit. E.g.,
  the control "/gnu/bar/foo" of an object "baz~" created with "baz~ baz1" has
  the fully qualified name "/baz1/gnu/bar/foo". This lets you distinguish
  different instances of an object such as, e.g., different voices of a
  polyphonic synth unit.

- Pd's input syntax for symbols is rather restrictive. Therefore group and
  control names in the Faust source are mangled into a form which only
  contains alphanumeric characters and hyphens, so that the control names are
  always legal Pd symbols. For instance, a Faust control name like "meter #1
  (dB)" will become "meter-1-dB" which can be input directly as a symbol in Pd
  without any problems.

- "Anonymous" groups and controls (groups and controls which have empty labels
  in the Faust source) are omitted from the path specification. E.g., if
  "foo" is a control located in a main group with an empty name then the fully
  qualified name of the control is just "/foo" rather than "//foo".  Likewise,
  an anonymous control in the group "/foo/bar" is named just "/foo/bar"
  instead of "/foo/bar/".

Last but not least, there is also a special control named "active" which is
generated automatically for your convenience. The default behaviour of this
control is as follows:

- When "active" is nonzero (the default), the unit works as usual.

- When "active" is zero, and the unit's number of audio inputs and outputs
  match, then the audio input is simply passed through.

- When "active" is zero, but the unit's number of audio inputs and outputs do
  *not* match, then the unit generates silence.

The "active" control frequently alleviates the need for special "bypass" or
"mute" controls in the Faust source. However, if the default behaviour of the
generated control is not appropriate you can also define your own custom
version of "active" explicitly in the Faust program; in this case the custom
version will override the default one.

EXAMPLES
========

In the examples subdirectory you'll find a bunch of sample Faust DSPs and Pd
patches illustrating how Faust units are used in Pd.

- The examples/basic/test.pd patch demonstrates the basics of operating "bare"
  Faust plugins in Pd. You'll rarely have to do this when using the wrappers
  generated with the faust2pd program discussed below, but it is a useful
  starting point to take a look behind the scenes anyway.

- The examples/faust directory contains all the examples from the Faust
  distribution, along with corresponding Pd wrappers generated with faust2pd.
  Have a look at examples/faust/faustdemo.pd to see some of the DSPs in
  action. Note that not all examples from the Faust distribution are working
  out of the box because of name clashes with Pd builtins, so we renamed
  those. We also edited some of the .dsp sources (e.g., turning buttons into
  checkboxes or sliders into nentries) where this seemed necessary to make it
  easier to operate the Pd patches.

- The examples/synth directory contains various plugins and patches showing
  how to implement polyphonic synthesizers using Faust units. Take a look at
  examples/synth/synth.pd for an example. If you have properly configured your
  interfaces then you should be able to play the synthesizer via Pd's MIDI
  input.

- The examples/seqdemo/seqdemo.pd patch demonstrates how to operate a
  multitimbral synth, built with Faust units, in an automatic fashion using a
  pattern sequencer programmed in Q. This example requires the Q interpreter
  as well as the Pd/Q plugin available from http://q-lang.sf.net.

WRAPPING DSPS WITH FAUST2PD
======== ==== ==== ========

The main component of the faust2pd package is a Q script faust2pd.q which
generates Pd patches from the dsp.xml files created by Faust when run with the
-xml option. Most of the sample patches were actually created that way. If you
want to use this, you'll also need the Q interpreter available from
http://q-lang.sf.net. (If you're compiling Q from source then you should make
sure that it is configured to include Q's XML module; this is required by
faust2pd to parse the XML files created by Faust.) Please note that Q 7.8 or
later is required.

If you want, you can run "make install" to install the faust2pd script under
/usr/local, or "make prefix=/your/path" to install it elsewhere. The prefix
should match Q's installation prefix. This will copy faustxml.q and faust2pd.q
to the Q library directory and create an executable link to the script under
$(prefix)/bin/faust2pd. Optionally, you can also run "make install-pd" to copy
the supporting Pd abstractions (faust2pd/faust-*.pd) to your $(prefix)/lib/pd/
extra directory, so that you can use the patches generated by faust2pd without
copying these abstractions to your working directory.

After installation you can run the script as "faust2pd filename.dsp.xml"; this
will create a Pd patch named filename.pd from the Faust XML description in
filename.dsp.xml. The faust2pd program understands a number of options which
affect the layout of the GUI elements and the contents of the generated patch;
run "faust2pd -h" for more information.

On Linux, the compilation of a Faust DSP and creation of the Pd patch
typically involves the following steps (again taking the freeverb module from
the Faust distribution as an example):

# compile the Faust source and generate the xml file
faust -a puredata.cpp -xml freeverb.dsp -o freeverb.cpp
# compile the C++ module to a Pd plugin
g++ -shared -Dmydsp=freeverb freeverb.cpp -o freeverb~.pd_linux
# generate the Pd patch from the xml file
faust2pd freeverb.dsp.xml

Just like the Faust plugin itself, the generated patch has a control input/
output as the leftmost inlet/outlet pair, and the remaining plugs are signal
inlets and outlets for each audio input/output of the Faust unit. However, the
control inlet/outlet pair works slightly different from that of the Faust
plugin. Instead of being used for control replies, the control outlet of the
patch simply passes through its control input (after processing messages which
are understood by the wrapped plugin). By these means control messages can
flow along with the audio signal through an entire chain of Faust units. (You
can find an example of this in examples/faust/faustdemo.pd.) Moreover, when
generating a polyphonic synth patch using the -n option then there will
actually be two control inlets, one for note messages and one for ordinary
control messages; this is illustrated in the examples/synth/synth.pd example.

The generated patch also includes the necessary GUI elements to see and change
all (active and passive) controls of the Faust unit. Faust control elements
are mapped to Pd GUI elements in an obvious fashion, following the horizontal
and vertical layout specified in the Faust source. The script also adds
special buttons for resetting all controls to their defaults and to operate
the special "active" control.

This generally works very well, but you should be aware that the control GUIs
generated by faust2pd are somewhat hampered by the limited range of GUI
elements available in a vanilla Pd installation:

- There are no real "button" widgets as required by the Faust specification,
  so "bangs" are used instead. There is a global delay time for switching the
  control from 1 back to 0, which can be changed by sending a value in
  milliseconds to the "faust-delay" receiver. If you need interactive control
  over the switching time then it is better to use checkboxes instead, or you
  can have faust2pd automatically substitute checkboxes for all buttons in a
  patch by invoking it with the -f a.k.a. --fake-buttons option.

- Sliders in Pd do not display their value in numeric form so it may be hard
  to figure out what the current value is. Therefore faust2pd has an option -s
  a.k.a. --slider-nums which causes it to add a number box to each slider
  control. (This flag also applies to Faust's passive bargraph controls, as
  these are implemented using sliders, see below.)

- Pd's sliders also have no provision for specifying a stepsize, so they are
  an awkward way to input integral values from a small range. OTOH, Faust
  doesn't support the "radio" control elements which Pd provides for that
  purpose. As a remedy, faust2pd allows you to specify the option -r MAX
  (a.k.a. --radio-sliders=MAX) to indicate that sliders with integral values
  from the range 0..MAX-1 are to be mapped to corresponding Pd radio controls.

- Faust's "bargraphs" are emulated using sliders. Note that these are passive
  controls which just display a value computed by the Faust unit. A different
  background color is used for these widgets so that you can distinguish them
  from the ordinary (active) slider controls. The values shown in passive
  controls are sampled every 40 ms by default. You can change this value by
  sending an appropriate message to the global "faust-timer" receiver.

- Since Pd has no "tabbed" (notebook-like) GUI element, Faust's "tgroups" are
  mapped to "hgroups" instead. It may be difficult to present large and
  complicated control interfaces without tabbed dialogs, though. As a remedy,
  you can control the amount of horizontal or vertical space available for the
  GUI area with the -x and -y (a.k.a. --width and --height) options and
  faust2pd will then try to break rows and columns in the layout to make
  everything fit within that area. (This feature has only been tested with
  simple layouts so far, so beware.)

- You can also exclude certain controls from appearing in the GUI using the -X
  option. This option takes a comma-separated list of shell glob patterns
  indicating either just the names or the fully qualified paths of Faust
  controls which are to be excluded from the GUI. For instance, the option -X
  'volume,meter*,faust/resonator?/*' will exclude all volume controls, all
  controls whose names start with "meter", and all controls in groups matching
  "faust/resonator?". (Note that the argument to -X has to be quoted if it
  contains any wildchards such as '*' and '?', so that the shell doesn't try
  to expand the patterns beforehand. Also note that only one -X option is
  recognized, so you have to specify all controls to be excluded as a single
  option.)

- Faust group labels are not shown at all, since I haven't found an easy way
  to draw some kind of labelled frame in Pd yet.

Despite these limitations, faust2pd appears to work rather well, at least for
the kind of DSPs found in the Faust distribution. Still, for more complicated
control surfaces and interfaces to be used on stage you'll probably have to
edit the generated GUI layouts by hand.

CONCLUSION
==========

Using Faust DSPs has never been easier before, so I hope that you'll soon have
much joy playing around with Faust DSPs in Pd. Add Pd/Q to this, and you can
program all your specialized audio and control objects using two modern-style
functional languages which are much more fun than C/C++. Of course there's an
initial learning curve to be mastered, but IMHO it is well worth the effort.
The bottomline is that Pd+Faust+Q really makes an excellent combo which
provides you with a powerful, programmable interactive environment for
creating advanced computer music and multimedia applications.

Acknowledgements
----------------

Thanks are due to Yann Orlarey for his wonderful Faust, which makes developing
DSP algorithms so much more easy and fun.


Enjoy! :)
October 2007
Albert Graef
