Syd 1.0.6

User Manual

Jim Bumgardner
9/29/97 - 10/18/97

Table of Contents

0.0 Preface

1.0 Introduction to Syd

  1.1 A Syd Tutorial
1.2 Where to go from here

2.0 Basic Unit Descriptions
  2.1 Sound Generating Units
2.2 Sound Modifier Units
2.3 Structure Units
2.4 Score Units

3.0 Expressions
  3.1 Variables
3.2 Operators
3.3 Functions

4.0 Menu Commands

Version History


0.0 Preface

First of all, I'd like to say hi to any CalArtians who are reading this - I attended that fine institution (music composition) from '80 to '84.

Those days were pre-MIDI for CalArts, but they did have two analog electronic music studios which featured Buchla 200 synthesizers, which were maintained by John Payne who must have had a love/hate relationship with them.

I am now a Macintosh programmer with a small collection of digital toys, but I miss those days of patch cords, razor blades and 2-track tape immensely.

One weekend, in late March of '97, in a fit of nostalgia, I decided to write a software synthesis program for my Mac that would share some interface elements with the Buchla 200. Working Buchla 200s are hard to come by, and I wanted to recreate the experience of patching modules together and hearing the results. So I spent the weekend writing a program called "SS" which stands for Soft-Synth (I've since changed the name to avoid confusion with other products with similar names). By the end of the weekend, I had a simple patchable interface working that was capable of generating some interesting sounds.

I've since spent considerably more than a weekend working on it, and have learned a bit more about digital audio. After learning about CSound and other Music-N languages, I incorporated some of the features in those languages, while still trying to retain some of the ease of use that the graphical "patch" interface provides.

I believe there are a few trends which prevent serious computer music tools from reaching a wider audience. One of them is that these tools have an unnecessary level of complexity, which is primarily due to historical precedent - performance considerations forced programmers to make systems which are awkward to use. CSound and similar systems are only easily understood if you are nearly knowledgeable enough to have programmed them yourself. Music compilers don't need to be this complex. The increasing speed of desktop computers should enable us to rethink how we approach these tools.

I'd like to offer the source code of this program to other interested amateurs - for any hobbyists who wish to tinker around with a digital synthesis program. If you'd like a copy, drop me an email. Also, if you develop some interesting sounds, I'd like to hear them - feel free to send me a copy of your patches.


Jim Bumgardner


1.0 Introduction to Syd

Syd, short for "Synthesis Demonstration" or "Synthesis Donut" is an instrument editor and software synthesizer. You can find the latest version of Syd here:


  • Graphical Interface for patching instruments and creating scores.
  • Some of the same power than can be found in text-based Music-N languages, such as CSound.
  • Provides mechanisms so instruments can be edited and tested without the need to generate a score.
  • Unlike Music-N languages, a score is treated as just another sound generating unit, which simplifies many operations. For example, one score can play another score as an instrument, and its output can be fed to a reverb module or amplifier, for post-processing.
  • The "Random Score" can generate sequences of random notes, as well as make permutations to an existing CSound score. For example, it can cause each note in a CSound score to trigger 100 simultaneous notes with slight variations in the parameters. It can also be used to augment or rearrange the parameters in a CSound score so it can be used with instruments which require alternate parameters.

Syd is still very much a work in progress. I am making it with the following goals in mind:

  1. Keep it simple to use - for example, you can patch an oscillator to a speaker, and hear a sound.
  2. Keep it nearly as flexible as CSound and other text-based music compilers.
  3. Avoid unnecessary complexity (e.g. "merge" "kamp" vs "amp", separation of "score" and "orchestra") by hiding performance issues from the user.
  4. Eventual support of such standards as MIDI, CSound, and Java.


1.1 A Syd Tutorial

The main interface in Syd is graphical. You create "patches" (algorithms for creating sound) by dragging the "modules" at the top into the large central area of the window. These modules are "patched" together using patch cords.

The patch cords indicate the direction of signal flow. In Syd signals generally flow either to the right or down. When a patch cords is coming out of a module, depending on the angle of the patch cord, it will either be coming out of the right side, or out of the bottom. On the other end, the patch cord will be "going in" to the left side or the top of another unit.

In this quick tutorial, we're going to create a simple FM-controlled oscillator.

You'll notice as you slide the mouse over the modules at the top, that each one identifies itself in the help box at the bottom of the window. Similarly, once you've constructed your patch, each element unit and patchcord will identify itself in this way, helping you keep track of what's what.

You'll notice there is already an output unit (the one with the speaker icon) in place. All patches require an eventual output, so this is already placed for you.

To add an oscillator, click on the oscillator icon (the second unit from the left with the sine wave on it) and drag the oscillator unit down into the main working area.

To patch the oscillator to the speaker, position the mouse over the right edge of the oscillator unit until the cursor changes into a phono-plug. Then click and drag, connecting the oscillator unit to the speaker unit. When you drag over the speaker unit, the speaker unit will highlight itself. Release the mouse. You'll see that the oscillator and speaker are now connected with a patch cord. Congratulations! You've made your first patch. Let's listen to it.

To synthesize the sound, hit the "Synthesize" button. During synthesis, the watch cursor will spin, and some text will appear in the log window. Synthesis should end fairly quickly, particularly if you are on a PowerMac.

After synthesis is done, you can listen to it by hitting the "play" button (If the patch is fast enough, you can listen to it while it is being synthesized -- see the Options menu).

What you're hearing is a sine-wave oscillation beating at 440 times a second. The entire sound lasts for 2 seconds. If you'd like to make the sound last longer, double-click on the output unit (the "speaker") - a dialog box will appear. In the dialog, change the "duration" value to some other time (how about 10.53 seconds?). You'll also notice that the sound is being saved to a file called "Untitled.aiff". You can change the file name here as well. Then hit "OK" and synthesize again. Aren't sine waves lovely?

Now, let's lower the pitch of the oscillator. Double click on the oscillator. Another dialog will appear. Change the "freq" value from "440" (the default) to "220". Then synthesize and play again.

You can view the sound you just made visually by using the "Graphics" option on the menu (Cmd-G). When the graphics window appears, a graphic representation of the last sound you synthesized will appear. The graphics window responds to mouse clicks and a few keystrokes as follows:

Click Zoom into the area clicked.
Option-Click Zoom out
Cmd-Click Zoom all the way out
Left/Right ArrowsScroll left and right

Now try creating a second oscillator and patching it to the first oscillator.

Modules typically have one output, and one or more inputs. Different color patch cords correspond to differing inputs.

Once you've patched the two oscillators together, pass the mouse over the patch cord going from the new oscillator to the old oscillator. You'll see from the help panel that the patch cord is going in to the "am" input of the first oscillator. Click on the patch cord and use the pop-up menu that appears to change it to go into the "fm" input of the oscillator. You'll see that once you've changed the assignment from "am" to "fm", the color of the patch cord will change from blue to green. Eventually you'll learn to recognize green patch cords at a glance as "fm" patch cords.

Once the patch cord is assigned to the "fm" input of the oscillator, you can refer to it's value within the oscillator by editing the oscillator's settings. Double-click on the first oscillator again. A dialog will appear.

Change the "frequency" setting from "220" to "220+fm*10", this will cause the oscillator to use the "fm" input to modulate it's frequency. Hit the "OK" button, synthesize and play the sound again.

It's worth noting at this point that you didn't really need to change the patch cord from "am" to "fm". You could have left it at "am" and then used the formula "220+am*10" - this would have had the same effect. The main purpose of changing the patchcord is to provide you with a visual understanding of what is going on. Since we're using the signal to modulate the frequency, "fm" is more appropriate. For some units, however, the choice of input does indeed make a difference. For example, on the filter units (and most other signal modifiers) the signal that is being filtered must always go in the "sig" input, while signals which are used to control the filter should go in the "ctl" inputs.


1.2 Where to go from here

At this point, probably the best way to learn more about Syd is to try some of the sample patches that have been included. Some have been designed to demonstrate particular features of the program, while others were included because they demonstrate particular synthesis styles. The "Patches" folder contains a file called "AAA_READ.ME" that describes each of these sample patches. I recommend reading this file and select a patch that sounds interesting to you.

You can load any of these patches via the file menu (you may edit multiple patches simultaneously in Syd) or simply double-click on the patch's icon in the finder.

After you load in the patch, listen to the sound it makes, and double click on each of it's units to see how they have been set up. If a particular unit being used in the patch mystifies you, look it up in this manual, and you'll find more information.

There are two units which are particularly interesting in Syd. One is the one that says "f(x)" on the icon - the Expression unit. This unit allows you to generate (or modify) a signal by typing in any mathematical expression - this manual describes the mathematical syntax that is used in these expressions. In addition, most of the other modules (such as the oscillator, the amplifier, the filters, the function table, and the random score module) also support expressions (in fact, you used one when you made the fm-controlled oscillator).

The other unit that is interesting is the "random score" module. This module can make a simple patch far more interesting by playing it with random values, and creating multiple notes which sound simultaneously (polyphany).

Some basic Syd units you should know about:

  • Loudness is usually expressed as a value between 0 and 1. dB must be converted if used.
  • Frequency is expressed in Hz (cycles per second)
  • Time is usually expressed in seconds


2.0 Basic Unit Descriptions

If you are not sure which unit is which, wave the mouse over the list of gadgets at the top of the window - the help text will indicate the name of the unit.


2.1 Sound Generating Units

  The oscillator is the basic waveform generator.

It accepts general expressions for frequency, amplitude and phase. In addition you can optional use an expression to define the waveform, in this expression, "t" will represent the position in the waveform from 0 to 1. You can create waveforms which vary over time using the variable "g" which represents global time.


   Freq (expression)
    This controls the frequency of the oscillation.
   Amp (expression)
    This controls the amplitude of the waveform.
   Phase (expression)
    This controls the initial phase of the waveform. It is expressed in radians (0 - 2pi). Larger values will "wrap over".
   Wave Type (radio buttons)
    This controls the type of waveform.
   Waveform Expression (expression)
    When the Wave Type is set to "Expression" - this expression determines the wave shape.

The frequency (like most of the other settings) can either be a constant, such as "440" or it can be an expression. For example, to make an FM controller oscillator, you could set Freq to "440+fm*0.1" which would cause it to use the incoming FM signal to modify the frequency.

There are some pitch conversion functions which allow you to specify pitch in different ways, for example, by MIDI note number, or by octave and step, see below.

The WaveType can either be a fixed waveform such as a sine, square, triangle or sawtooth wave; or it can be computed using an expression you provide. For example, the following expression makes a sine wave with two harmonics.

sin(t*2*pi)+sin(2*t*2*pi)/2 + sin(3*t*2*pi)/3

  Generates a plucked-string sound using the Karplus/Strong algorithm. These sounds are generated by filling a buffer with random values and then smoothing the values over time. This generates an interesting sound and has the added benefit of being extremely fast. Patches based on this sound can often be generated in real-time on a PowerMac.


   Variant (constant)
    Currently no effect - I will eventually support both plucked string sounds and drum sounds.
   Frequency (expression)
    Frequency (pitch) of the sound. See the section on oscillators for a discussion of frequency.
   Amplitude (expression)
    Amplitude (loudness) of the sound.
   Duration (expression)
    How long the sound should last.
   Decay (expression)
    Controls the decay factor, or how quickly the harmonics drop out of the sound.

  Generates a maraca-like sound using Perry Cook's Maraca simulation algorithm, which appeared in the Fall '97 Computer Music Journal (Vol 21, #3).


    The resonating frequency of the Maraca shell. Raising this frequency will make the Maraca sound smaller. Lowering it will make it sound bigger.
    Controls how narrow the resonating frequency band is. The default value works nicely.
    Controls how often the "beads" hit the "shell". Increasing this value will make the maraca sound like it has more beads.
   System Decay
    Controls how fast the "beads" lose energy after the initial "shake". Raise this value to create an "anti-gravity" maraca.
   Sound Decay
    Controls how fast the sound decays after the beads hit the shell.

  Reads a sample (AIFF) file and outputs the sound contained in the file. At the moment, this unit can only read AIFF files which contain uncompressed, monophonic, 8 or 16-bit sounds. This restriction will be dropped in the future.


   File (file spec)
    Name of the sample file to playback.
   Timescale (expression)
    Determines speed of playback. 1.0 is normal speed.

Noise Generator
  Generates random values from 0-1. Note: In an expression, the symbol "?" produces the same kind of signal.


   seed (constant)
    Provides a seed for the random number generator.
   randomize (boolean)
    If true, a random seed will be chosen based on the system time.

  Expressions can be used both for generating and modifying sounds.

The expression syntax used by the Expression Unit also applies to the input fields of most of the other units (unless those fields are described in this manual as accepting "Constants").

See section 3.0 for more on expressions.


   expression (expression)
    The expression to compute.

These signals can be referred to in the expression.

Hammer Bank
  Note: This unit is still "under construction" and will probably be modified in future versions of the software.

The HammerBank simulates a piano-like instrument with 128 strings, which are activated by hammers, and have dampers. The action of the hammers and dampers is triggered using one or more Hammer Actuator Units, see below. These units can be used to simulate an instrument which has sustain properties which are triggered independent of the notes. Most of the fields take expressions which can use the "k" variable (key number) to create characteristics which change relative to the register of the key.

See the "HammerTest" patch for an example of a HammerBank in action.


   Bank# (constant)
    The number to assign to this bank (used by HammerActuators).
   k->Freq (expression)
    This is used to compute the key to frequency function. cpsmidi(k) will produce an equal tempered tuning which corresponds to MIDI note number, but you can use alternate tunings if you like.
   k->Amp (expression)
    This is used to compute the relative amplitude of each key. A value of 1.0 will produce an even amplitude across the whole keyboard.
   k->Attack (expression)
    This is used determine the length of the attack after the hammer strikes the string.
   k->Decay (expression)
    This is the decay coefficient which represents the amplitude of the note 1 second after the hammer has struck, using an exponential decay. On a real keyboard, lower notes will have a longer decay. You can accomplish this by making this value a function of k.
   sustain (expression)
    This is an expression which is computed during signal generation to determine if sustain is on, which causes all strings to behave as if they are undamped. You can simulate the effect of a sustain pedal by triggering this with a G variable from another instrument. Set this to 1 if you want permanent sustain.
   Waveform (expression)
    If no input instruments are used, the module will use this expression to generate the waveforms for each string, it is equivalent to an internal oscillator.
   i1,i2,i3 etc.
If provided, this input instrument will be cloned, once per string, to provide the sound, rather than using the internal waveform function. The amplitude of this instrument will be automatically scaled by the energy value of the string. Instruments 2 and higher are not yet supported.

ctl,ctl2,ctl3, etc.
These are control signals which can be used in the other settings.

Hammer Actuator
  Note: This unit is still "under construction" and will probably be modified in future versions of the software. This unit can be used to activate the hammers and dampen/undampen the strings of a Hammer Bank unit (see above). See the "HammerTest" patch for an example. Multiple Hammer Actuators attached to a single note event can be used to create "sympathetic resonance" effects. In a typical configuration using a Score unit, a single HammerBank will sound throughout the entire piece, while Hammer Actuators will be triggered for each note event.

See the "HammerTest" patch for an example.


   bank# (constant)
    The Hammerbank to affect.
   key# (expression)
    The key to strike or undampen. This should be a number from 0-127.
   trigger (expression)
    A trigger signal which causes this actuator to trigger. To strike a key at the beginning of a note event, use a value of "1". To cause a key to be damped at the end of a note event, provide a value which will go to 1 near the end of the note event, such as cond(t
   velocity (expression)
    The force with which to strike the key (a value from 0 to 1). This value is added to the key's current energy, over a time interval set by the key's attack period.
   undamp (expression)
    Indicates whether the key should be damped (0) or undamped (1).
   sig,sig1,sig2, etc.
ctl,ctl1,ctl2, etc.


2.2 Sound Modifier Units

  Amplifies or attenuates the input signal, and then adds an offset value.


   scale (expression)
    A constant or time varying formula to scale the amplification.
   offset (expression)
    An offset to add after amplification.
    The signal to be amplified
   ctl,ctl1,ctl2 (etc)
    Control signals which can be used to create time-varying amplification effects.

For example, to scale a sawtooth wave (which normally outputs values from -1 to 1) to output values from 0 to 1, use a scale of .5 and an offset of .5

Envelope Generator (ADSR)
  This is a bare bones ADSR envelope generator. The envlope generation facility is probably going to be extensively reworked to support graphical editing of envelope shapes. The current unit generates a signal using the settings you provide numerically.


   Attack Time (constant)
Attack Level (constant)
Decay Time (constant)
Decay Level (constant)
Sustain Time (constant)
Sustain Level (constant)
Release Time (constant)
    These control the overall shape of the envelope, determining the timing and value for 4 different amplitude levels (the last one is assumed to be zero). All these fields must be constants, not expressions.
    This is the overall duration. Typically, the envelope values should be expressed so that the envelope takes one second. Than this value can be used to stretch or shrink the envelope.
   trig (no longer used)

It is common to patch an Envelope Generator into a function table to generate a table with the envelope values in it. An oscillator can use the values in the function table with an expression like: "p4*ftab(p5,t/p3)" in which p4 is the overall amplitude of the note, p3 is the duration of the note and p5 is the function table number.

Envelopes used with function tables should have an overall length of 1. Envelopes used directly with notes should have an overall length equivalent to the duration of the note (commonly p3). For the most flexibility, the ADSR times should assume an envelope with a length of exactly 1 second, so the duration field can be used to scale it to arbitrary lengths.

  This module is used to mix together and attenuate multiple signals which might otherwise cause clipping when added. The output signal is attenuated based on the number of input signals.



The Mixer module will always attentuate the signal if more than one signal is coming into it. If you would simply like to add some signals together, you can simply patch them all into the same input. In some cases, it is useful to add them together before patching them somewhere (for example before patching into a score, so as to reduce to a single instrument). In this case, you can use an Amplifier with a gain of 1.0 to add units together.

Filter (2nd Order Section)
  This module is used to create a common kind of filter called a 2nd-order Section. Such a filter can be expressed as outputting a series of vaues y[0...N] based on a series of input values x[0...N] with the following formula: y[n] = a0*x[n] + a1*x[n-1] + a2*x[n-2] + b1*y[n-1] + b2*y[n-2] Note: The "classic" 2nd order section uses subtraction, rather than addition for the "b1" and "b2" terms. If you want this, use negative values for the b1 and b2 coefficients. If you are looking for a more "musical" filter that is easier to understand, I suggest using the Butterworth filter (see below).


   a0 (expression)
a1 (expression)
a2 (expression)
b1 (expression)
b2 (expression)
    These are the coefficient values for the filter. They can be time-varying expressions, or constants.

    This is the signal you wish to filter

   ctl,ctl1,ctl2,ctl3 etc

    These are for control signals which can be used to modify the coefficients, creating time-varying effects such as filter sweeps.

Filter (Butterworth)
  This unit implements lo-pass, hi-pass, band-pass and band-reject Butterworth filters.


   Filter Type (pull down menu)
    Allows you to select the type of filter you want. The default is band-pass.
   Freq (expression)
    For lo-pass and hi-pass filters, this is the cutoff frequency. For band-pass and band-reject filters, this is the center frequency.
   Band (expression)
    Only relevent for band-pass and band-reject filters - this is the width of the band on each side of the center frequency. It is commonly expressed as a percentage of the center frequency.

    This is the signal you wish to filter

   ctl,ctl1,ctl2,ctl3 etc

    These are for control signals which can be used to modify the coefficients, creating time-varying effects such as filter sweeps.

  A simple delay unit. The output y[n] is expressed as (a0*x[n] + a1*x[n-delay])


   delay (expression)
    Controls the length of the delay between the initial sound and it's first reverberation - expressed in seconds. If the delay is too large, you may run out of memory. You can use time-varying expressions (a time-varying delay will cause pitch shifts).
   a0 (expression)
    Controls the gain of the original signal.
   a1 (expression)
    Controls the gain of the delayed signal.
   feedback (boolean)
    If true, this causes the delayed signal, rather than the original signal to be stored in the delay line (making this an IIR rather than a FIR filter). This creates multiple repeats, which are useful for reverberation effects. However, keep in mind you can overload the signal if the delay gain is too high.

    This is the signal you wish to delay

   ctl1,ctl2,ctl3 etc

    Control signals which can be used to create time-varing delay effects.

Threshhold Unit
  Outputs 1 if the input signal is above a particular threshhold value, otherwise, outputs 0.


   cutoff (expression)
    This controls the threshhold value - it defaults to 0.5.

    The signal to monitor.

Sample and Hold
  When a trigger is received, this samples the current intput signal and continues to output that value until the next trigger is received. Try using a square wave oscillator for a trigger.


    The signal to sample.

    The trigger signal - when this signal goes over 0.5, it will cause the next sample to be stored.

  Inverts the signal by inverting its sign (multiplying by -1).



    The signal to invert.

  Smoothes the signal by averaging subsequent values. This is a simple lowpass filter where y[n] = (x[n]+x[n-1])/2. For more predictable and controllable effects, use the (slower) Butterworth filter.



    The signal to smooth.


2.3 Structure Units

The following units control the overall structure and form of the patch, rather than generating or modifying audio signals directly.

Speaker (Output)
  There is always at least one speaker unit. This is meant to be the final terminus for the patch. Any signal being fed into the speaker is "heard". As described below, the settings are only meaningful if the patch is being used as the "main instrument". If the patch is being used as a folder instrument, the output settings are ignored.


   output to memory (radio button)
    Causes the samples to be stored in a 440k buffer in RAM. If the duration of the sound is larger than the buffer (20 seconds at 22050 sampling rate), a "sliding window" will be used so you can see the results of the whole synthesis in the graph window, and hear the whole thing, if Listen is turned on. This is a useful option for previewing long samples when you don't have a lot of free disk space.
   ouput to aiff file (radio button)
    Causes the sound to be stored in an AIFF file. You'll be prompted for the file name.
   duration (constant)
    The overall time of the sound to be generated.

If you are outputting a CSound score, you would probably prefer for the score itself to determine how long the piece is. Sadly, you're out of luck, until I add that feature.

   sample rate (constant)
    The sample rate of the sound.

    The signal to output.

  Folders are used to encapsulate entire instruments, which are stored in separate patch files. This makes it easier to create complex instruments without clutter. For an example, look at the "combo.syn" patch, which combines 2 folder instruments.

Folders are also useful for defining the instruments to be patched into a score. A score might need 10 instruments patched into it, and there isn't enough space in the patch window to fit all of them.


   file (filespec)
    The patch file to patch in.
   f1,f2,f3 etc

    Inputs into the folder instrument. If the folder instrument needs some particular parameters, this is how you pass them to it. The folder patch file can use the "Folder Input" units (see below) to retrieve these values, or refer to them directly in expressions (e.g. "f1*100").

Folder Input
  Folder inputs are used to document the inputs into an instrument which is meant to be played as a Folder Instrument. They also provide default values for these inputs so the instrument can be tested on its own, without having to being played as a folder instrument.

For an example, see the "quietreverb.syn" patch, which accepts a folder input.


   F number (constant)
    Specifies which folder input to retreive, when this patch is played as a folder instrument.
   description (string)
    Provides a comment to identify this signal.
   default (expression)
    Provides a default value to use, so this patch can be tested without being played as a folder instrument.

Param (Score) Input
  Parameter (Score) Inputs are similar to Folder Inputs. They are used to document the inputs into an instrument which are meant to be provided by a Score. They are similar to Folder inputs, but refer to the parameter values (p1,p2,p3 etc) which are generated by a Score unit. They also provide default values for these inputs so an instrument can be tested without a score. See Scores, below. For an example, see the "shepsco.syn" patch, which reads parameters from a score file and passes them to a folder.


   P number (constant)
    Specifies which parameter to retreive, when this patch is played by a score.
   description (string)
    Provides a comment to identify this parameter.
   default (expression)
    Provides a default value to use, so this patch can be tested without being played by a score.

Global Variable Assignment
  These units are used to load values into global variables, which can then be accessed from other instruments (using the notation g0,g1,g2 etc.). These units output 0, so they can't be used in a path which is directly generating an audible signal (however, you can fork off such a path to create the assignment).


   G number (constant)
    Specifies which global variable to assign.
   value (expression)
    Provides the value which is to be loaded into the global variable. Typically this is a function of the signal being fed into the unit, e.g. "sig".
   description (string)
    Provides a comment to identify this purpose of this variable.

    Specifies signals which can be fed into the global variable.

Function Table (ftab)
  Function tables are provided as a means of speeding up calculations. A function table's contents are precomputed when the instrument is initialized. Subsequently, the table's contents can be accessed from any expression using the function ftab(n,t) where "n" is the function table number, and t is a number from 0 to 1 which accesses a particular table element. The (slower) function ftabi() [ not yet supported ] can be used if linear interpolation between table values is desired. All your tables should have different numbers, and ideally, tables should not be defined in folder instruments.


   ftab number (constant)
    Assigns this formula to a particular global function table number. This allows the table to be addressed by various instruments using the expression ftab(n,t) where "n" is the table number.
   ftab size (constant)
    Determines the number of entries in the table. For control signals, larger values will prevent aliasing noise.
   formula (expression)
    The formula used to compute the table's contants.

    This signal will be generated only when the function table is calculated. For units patched into the function table, the "t" value will go from 0-1 as the table is filled in, regardless of the length of the table. The ADSR units are designed to work with function tables, although other units can be used as well.


2.4 Score Units

Score units are used to create entire pieces of polyphonic music. They use the instruments that are patched into them to sound each note in a "score". Although you can patch them together as you can the other units, their behavior is considerably different. Each input into a score unit will be treated as a separate "instrument". Whenever a note is played in the score, a unique "instance" of the sub-patch that corresponds to the instrument number will be temporarily created and sounded for the duration of the note. Multiple instances of instruments allow for multiple notes to sound simultaneously, creating polyphony.

If the score refers to multiple instrument numbers, you can patch in multiple instruments - one for each type used in the score. I suggest using folder instruments (see above) for this purpose, to reduce icon clutter. In this case, you would have one patch for each instrument, and one "master" patch which shows how those instruments are assigned to the score.

Since scores allocate instances of instruments, they may cause considerable amounts of memory to be consumed. Since Syd is still not very well behaved when it runs out of memory, I suggest saving your work before hitting the "Synthesize" button.

Score modules use the same conventions as CSound score files, where the note parameters are provided in variables named p1, p2, p3 etc. The first three parameters have fixed meanings: p1 is the instrument number, p2 is the start time of the note, p3 is the duration of the note. Subsequent parameters can be used in any way you want. In a simple instrument, p4 might be amplitude and p5 might be frequency or midi note number.

Syd treats score modules just like other modules. This means that a score module can "play" another score module as an instrument, and the output can be patched into a sound module (e.g. reverb or amplifier) for post processing.

The ability to patch two score modules together is particularly useful when used in conjunction with the random score unit, which generates events based on a set of formulas. For example, one way to use the random score unit is to thicken an instrument that is being played by a CSound score - the random score can cause each note event to trigger multiple note events, each with slightly randomized parameters, turning one instrument into a whole chorus.

Random scores can also be used to correct, adjust, swap or embellish the parameter values in a CSound score, allowing it to be used with an instrument which wasn't originally designed to be used with that score. This means you will spend less time modifying instruments to work with different scores, instead, you can use the random score unit to "map" a particular score to a particular instrument.

CSound Score
  The CSound Score unit reads a "CSound" score file and plays it using the instruments that are patched into it. At the moment, Syd's support for CSound scores is very minimal - function tables and ramps are not yet supported. The sample patch "prelude_pluck.syn" shows an example of CSound score being played.


   file (file spec)
    Specifies the CSound score (.sco) file to use.
   i1,i2,i3 etc...

    Instruments to patch into the score. Each note event in the score will create an instance of the corresponding instrument which will last for the duration of the note.

MIDI Score (work in progress)
  The Midi Score unit (when it is implemented) will read a standard MIDI file and play it, assigning the parameters as follows:

   p1   channel number+1
   p2   start time
   p3   duration
   p4   velocity (0-127)
   p5   pitch# (0-127)

This unit has not been implemented yet. In the mean time, if you want to read MIDI files, I suggest getting a copy of CSound and using one of the MIDI to CSound conversion utilities.


   file (file spec)
    Specification of a standard MIDI file.
   i1,i2,i3 etc...

    Instruments to patch into the score. Each note event in the MIDI file will create an instance of the corresponding instrument (based on MIDI channel number) which will last for the duration of the note.

Random Score
  The random score unit creates a series of notes (or more accurately - "events"), which are generated using random numbers or other formula. It has many uses, including creating aleatoric scores, testing instruments and fattening sounds. Various options allow you to specify the number of notes, their starting times, durations, and other parameters.

A random score can be played by another random score. In this case, the formulas in the random score can refer to "p2 p3 p4" etc., which refer to the note values provided by the parent score which is playing it.

If an instrument isn't being played by a score module, the values of p1,p2,p3 are assigned reasonable defaults. In particular:

    p1 is 1
    p2 is 0
    p3 is the total duration of the sound.
    p4 is 1.0
    p5 is 440

By nesting random scores in this manner, you can achieve a great deal of complexity.

In any of the formulas used in a random score, the variable "n" refers to event number, from 0 to (#events-1).


   # Events (expression)
    Determines how many notes (or events) will be generated. A constant like "12" will generate 12 notes. "P3*2" will generate a number of notes relative to the duration of the parent event.
   P1 (instrument#) (expression)
    Used to select an instrument. Instrument numbers start at 1. If you use "0", it will select the first instrument available. To alternate between two instruments, you could use "1 + n mod 2".
   P2 (start) (expression)
    Used to set the start time of the note. Examples are "?*p3" which makes a random start time, and "n*p3/12" which generates 12 sequential start times.
   P3 (duration) (expression)
    Used to set the duration time of the note. Examples are "?*p3" which makes a random start time, and "n*p3/12" which generates 12 sequential start times.
   P4-P16 (expression)
    Used to add optional parameters, such as amplitude and frequency, to each event.
   i1,i2,i3 etc...

    Instruments to patch into the score. Each note event in the score will create an instance of the corresponding instrument which will last for the duration of the note.

   ctl,ctl1,ctl2... (still to come)

    These inputs can be used to provide signals to use in your note generation formulas. These inputs are not "instantiated" in the way the instrument inputs are.


3.0 Expressions

The expression syntax used by the Expression Unit also applies to the input fields of most of the other units (unless those fields are described in this manual as accepting "Constants").


3.1 Variables

  input vars
   Any patches into a unit can be referenced by using the input variable name. For example, the inputs into an oscillator are "am, fm, amwidth and fmwidth". These names are provided as mnemonics for their suggested uses, the signals can be used in any manner you wish. So for example, the pitch of an oscillator might be specified as "440+fm", where "fm" is the input from another oscillator.

See the specific unit definitions for a description of their inputs.

  instrument vars
   The variables "p1", "p2", "p3" etc. are provided when the instrument feeds into a Score generator (such as a Random Score unit or a CScore Score Unit). These are the parameters provided by the instrument events in the score. Generally, p2 is the start time of the note, p3 is the duration of the note. For the random score unit, p4 is the amplitude (0-1) and p5 is the pitch (cps).

You can use the "P-Input" module to assign reasonable defaults to these values as a way of testing a particular instrument without a score. Otherwise, if you are not using a score, they will be assigned reasonable defaults as follows:

    p1 = 1
    p2 = 0
    p3 = duration of sound
    p4 = 1
    p5 = 440
    all others = 0

  global vars
   The variables "g0", "g1", "g2", etc are provided for storage of global variables, which allow crosstalk between separate instruments. You can store a value into a global variable using the "Global Variable Assignment" units.

  built-in variables
   d duration of piece in seconds
   v mix of all input signals (e.g. "sig", "am","fm")
   t local time
For a note this is note time.
For an oscillator waveform, this is wave form position (0-1).
For a function table, this is table positoin (0-1).
For anything else this corresponds to global time.
   n note time
The time relative to the note being sounded (provided by the score modules).

This has 2 possible values. For a simple unit, such as an oscillator, this refers to the time of the note being sounded. It starts at 0, at the beginning of the note, and then increments as the note progresses.

If the unit isn't patched into a score, this value will correspond to g, or global time.

   i note number
If the expression is being used to generate the notes of the random score, this value will correspond to the note number, from 0 thru n-1, which is useful for creating linear note spacing. In versions of Syd prior to 1.0.6, the variable "n" was used for this purpose, and this method is still supported for backward compatability.
   k key number
If the expression is being used in a Hammer Bank unit, this value will correspond to the key number, from 0 thru 127.
   a string amplitude
If the unit is connected to a HammerBank unit, this value contains the string energy, which will start around 1.0 when the string is struck, and then decay using the decay coefficient provided in the HammerBank module.
   g global time
The time relative to the section as a whole.
   r sample rate
The current sampling rate (determined by the output module).
   pi 3.14159... (pi)
On Macintoshes, the pi symbol may also be used (Option-P).
   pi2 2*3.14159... (pi*2)
The value of pi multiplied by 2.
   E The constant E
This is the base of natural logarithms.
It is equivalent to exp(1).
   ? Random number (0 >= r < 1)
The random number generator used is a fairly decent one, as described in Stephen K. Park and Keith W. Miller, "Random Number Generators: Good Ones Are Hard to Find", Communications of the ACM, vol. 31, p. 1192 (October 1988).

Note: At the moment, I have not designed a good mechanism for controlling random number seeds on a module by module basis. Every time a patch is used, the random numbers will be different.


3.2 Operators

  + addition
  - Subtraction (x - y)
  - Negation (- y)
  * Multiply
  / Divide
  % Modulo (also "mod")
  ^ Raise to Power
  & Bitwise AND
  | Bitwise OR
  ~ Bitwise Invert
  xor Bitwise XOR
  and Logical AND (also "&&")
  or Logical OR (also "||")
  not Logical NOT (also "!")
  == Equality
  > Greater than
  >= Greater than or equal
  < Less than
  <= Less than or equal
  <> Not Equal
  != Not Equal


3.3 Functions

Syd has a fairly rich set of functions available -most of these were inherited from the expression parser that is used in my Image Processing software "Pixel Magic". This means that if you like playing with the Mandelbrot set, you can use it to generate sounds too.

functions - basic math & trig

  int(x) Convert to Integer
  sqrt(x) Square Root
  sin(x) sine
  cos(x) cosine
  sin2 sine squared
  cos2(x) cosine squared
  sin3(x) sine cubed
  cos3 cosine cubed
  tan(x) tangent
  asin(x) arc sine
  acos(x) arc cosine
  atan arc tangent
  cosh(x) hyperbolic cosine
  sinh(x) hyperbolic sine
  tanh(x) hyperbolic tangent
  log(x) natural logarithm
  log10(x) base 10 logarithm
  fabs(x) absolute value
  abs(x) absolute value
  exp(x) E to the x power

functions - f tables

  ftab(n,t) Access function table N (0+) at position T (0-1)
  ftabw(n,t) Access function table N (0+) at position T (0-1), wrap
  ftabp(n,t) Access function table N (0+) at position T (0-1), pin
  ftabi(n,t) Access function table N (0+) at position T (0-1), interpolate
  ftabip(n,t) Access function table N (0+) at position T (0-1), interp+pin
  ftabiw(n,t) Access function table N (0+) at position T (0-1), interp+wrap

These functions are used to access the tables which are created by the "FTAB" units. The basic ftab() function uses the value of T to access the values of Funtion Table #N. If T is less than 0 or greater than 1, then a value of 0.0 will be returned. Otherwise, the value of T (from 0 to 1) is used to access a value from the beginning to the end of the table.

The "Pin" variant will pin to the beginning and ending values of the table, that is values less than 0 will be treated like a 0, and values greater than 1 will be treated like a 1.

The "Wrap" variant will wrap over, using the fractional part of T to access the table. So, for example, 7.1 is treated the same as 0.1.

The "Interpolating" units will use linear interpolation, which is slower, but can reduce the aliasing caused by short tables.

functions - pitch converters

  These functions are typically used for converting a linear representation of pitch to oscillator frequency which is supposed to be expressed in cycles per second (which is logarithmic).

In the following functions, the pitch of A 440 (A above Middle C) can be represented as follows:

  cps440(440 cycles per second)
  pch8.09(8 octaves + 9/12 of an octave)
  oct8.75(8 octaves + .75 of an octave)
  midi69(69th note on keyboard)

  cpspch(x) Convert cycles per second to pitch
  cpsoct(x) Convert cycles per second to octave
  octpch(x) Convert octave to pitch
  octcps(x) Convert octave to cycles per second
  pchoct(x) Convert pitch to octave
  octmidi(x) Convert octave to MIDI note
  cpsmidi(x) Convert cycles per second to MIDI note

functions - signal modifiers

  These functions, which are borrowed from CSound, are useful for creating envelopes and otherwise modifying signals.

   This function computes a straight-line envelope which has a total duration of duration, an attack time of attack and a decay time of decay. The values rise from 0 to 1, and then back to zero.
   This function computes a simple envelope with a straight-line attack and exponential decay, similar to many natural sounds. The total duration is equivalent to attack+decay. The decayval controls the rate of cutoff, and is typically around 0.01. Values which are too large will produce a noticeable click, while values that are too small will shorten the sound.
   This function limits the value of v to fall between the values of min and max. If v < min, then min is returned. If v > max, then max is returned. If max < min then a constant value of (min+max)/2 will be returned.

functions - fractals and noise

  mandel(x,y) Mandelbrot Set, level set method (also mand)
  manc(x,y) Mandelbrot Set, CPM method
  man3 Mandelbrot cubed
  julia(x,y,p,q) Julia Set, level set method
  dragon(x,y,p,q) Dragon Fractal
  fbm(a,b,c,d,e,f) Fractal Brownian Motion (broken)
  noise(x,y) 2D Noise
  turb(x,y) 2D Turbulence (fractal noise)
  noise3d(x,y,z) 3D Noise
  turb3d(x,y,z) 3D Turbuluence (fractal noise)
  gnoise3d(x,y,z) Alternate Noise Function
  gturb3d(x,y,z) Alternate Turbulence Function

functions - misc

  cond(exp,a,b) if exp is non zero, a, otherwise, b.
  angle(x,y) angle from 0,0 to x,y
  dist(x,y) distance to x,y
  fib(n) Fibonacci Series
  prime(n) Prime number function


4.0 Menu Commands

   Creates a new patch document.
   Opens an existing patch document.
   Closes the current window.
   Saves the current patch document to disc. If you haven't named it yet, you'll be asked to assign a name.
   Saves the current patch document to disc under a new name.
 Page Setup
   Printing is currently unimplemented.
   Exits the Syd application.
   Most editing operations are unimplemented, except for "Clear" which deletes the selected unit.
   Duplicates the selected unit, copying its values.
 Select All
   Opens a log window, which displays various messages during synthesis.
   Opens a window which displays a graphic representation of the last sound synthesized. The graph window responds to the following clicks and keystrokes:

Click               Zoom into the area clicked.
Option-Click        Zoom out
Cmd-Click           Zoom all the way out
Left/Right Arrows   Scroll left and right

If the graph window is open during Synthesis, the sound will be regraphed every few seconds. This may slow down the synthesis considerably as long sounds take proportionally longer to graph.

 Show Memory
   If the log window is open, this option will cause the free memory to be displayed before and after synthesis - primarily used by the author as a debugging aid.
 Listen during Synth
   Causes the samples to be sent to the Sound Manager for playback during synthesis. If the patch is too slow to compute (as most of them are), you will hear gaps and clicks. You may also hear clicks when the hard disc is accessed.


Version History

3/31/97 Version 0.9.9 Released to Public on 3/31/97 "as is"

9/27/97 Version 1.0

  • Various Bugs Fixed
  • Lots of new features- see manual.

9/29/97 Version 1.0.1

  • Added support for 68k macs with no floating point unit (SLOW!)
  • Added "pluck" module based on Karplus/Strong Algorithm.
  • Added "Log" window for debugging.
  • Gadget panel now has two rows.
  • Sped up audio graphics rendering.
  • Added/removed some sample patches.

10/3/96 Version 1.0.2

  • Added necessary fixes to create a 68k w/FPU version.
  • Added support for interleaved tempo statements in CSound score files.
  • Added support for disk-based output, allowing for much larger output files.
  • Added SampleFile module which plays samples from AIFF files.
  • Fixed bug in which modules could be dropped on gadget bar.
  • Added Real-time audio preview during Synthesis.
  • Fixed memory-output to use a sliding window so long patches can be previewed without saving to disk.

10/14/96 Version 1.0.3

  • Fixed a bug which caused 680x0 version to crash.
  • Fixed bug in graph window (Y was inverted).
  • Added Band Pass Filter module.
  • Added Maraca module based on Perry Cook's algorithm in CMJ Vol 21, #3
  • Made filters support general expressions.
  • Added support for "+" in CSound scores.
  • Added sign() function.
  • Modified ADSR to work with function tables.
  • Added initialization feeback via log window.

10/16/96 Version 1.0.4

  • Added Butterworth filters (lopass, hipass, bandpass, bandreject)
  • Removed Band Pass Filter from version 1.0.3
  • Replaced FIR filter with more useful 2nd-order section
  • Added "clarinet" and "choir" sample patches.
  • Increased available parameters in "rscore" module.

10/17/96 Version 1.0.5

  • Did a second pass on the Manual - it is much more complete now.
  • Output file spec  is now specified from Output module, and is saved with patch.
  • Fixed Random Score unit to use 1 (rather than 0) as the lowest instrument number, so as to be consistent with CSound scores.
  • Fixed bug with parsing .syn files with old style Random scores.
  • Fixed bug with saving and reading expressions which contain spaces.
  • Fixed bug in which scores referring to non-existent instruments caused a crash during synthesis.
  • Removed some of the more redundant patches from the sample patches folder.
  • Changed settings for reverb unit, added expressions.
  • Changed threshhold unit cutoff to an expression.
  • Added ctl inputs to amplifier.
  • Added alternate "sig" inputs to filters to "ctl" inputs.

10/29/96 Version 1.0.6

  • Changed named from "SoftSynth" to "Syd" to avoid confusion with similarly named programs.
  • Fixed bug with Butterworth Bandpass filter which caused it to cease output if bandwidth dropped to zero at any point.
  • Fixed bug with FTables not initializing properly.
  • Added ftabw(),ftabp(),ftabi(),ftabiw() and ftabip() functions.
  • Added linen(),linenr() and limit() functions.
  • Added 'r' variable for sample rate.
  • Added 'pi2' constant.
  • Added 'E' constant (same as exp(1)).
  • Added Risset ClarinetWS and Bell patches.
  • Added HammerBank and HammerActuator units (still in progress).
  • Added Global Variable Assignment unit.
  • Added support for "i" variable in random scores to represent note number (formerly we were using "n" which was inconsistent with its other meanings).
  • Added support for "k" variable in Hammerbank which is used for key number.
  • Added support for "a" variable in Hammerbank which is used for string energy.