A basic software synthetizer programmable in Python and a dedicated language.
To run, open or compile SynthScript.opal
, and pass it a file to run as a command line argument.
--compile
- Tells the program that the given file is written in SynthScript and needs to be compiled.
- Usage: --compile
--export-tracks
- Generates a .wav file for each playback channel.
- Usage: --export-tracks
--realtime
- Skips the rendering process and plays the source code directly. This option will produce a lower quality sound and more inaccuracies in playback.
- Usage: --realtime
--cupy
- Uses the GPU to perform NumPy operations. Results in a significant performance improvement. Requires the
cupy
module installed. - Usage: --cupy
- Uses the GPU to perform NumPy operations. Results in a significant performance improvement. Requires the
An Instrument
is a way to combine waveforms and Process
es.
Instrument(**instruments, postProcess, preProcess, static)
**instruments
: a list of keyword arguments used to refer to otherInstrument
s or waveforms.postProcess
: (Optional) used to refer to aProcess
object for post processing;preProcess
: (Optional) used to refer to aProcess
object for pre processing;static
: If set toTrue
, theInstrument
will not react to variable changes. Useful for performance reasons.False
by default.
A Process
is a way to combine effects.
Process(**effects, static)
**effects
: a list of keyword arguments used to refer to otherProcess
objects or effects.static
A Midi
is a way to include and play midi files.
Midi(file, instruments)
file
: the midi file.instruments
: a list of instruments mapped to midi channels. If not set, square waves will be used for every channel.
A SoundFont
is a way to include and use .sf2
files.
SoundFont(file)
file
: the.sf2
file. This class contains agetInstrument
method that will find an instrument given its name.
A SoundFontInstrument
lets you use a specific instrument from a SoundFont
SoundFontInstrument(soundFont, preset, bank)
soundFont
: theSoundFont
you want to get the instruments from.preset
andbank
let you pick a specific instrument. Both arguments are optional.
It's not recommended to mix SoundFontInstrument
s and waveforms in the same track when using midi files due to approximation errors.
Waveforms all take two basic arguments when generated:
Wave(amplitude, static)
amplitude
: the waveform's amplitude;static
Available waveforms are:
Square(amplitude, duty, static)
duty
: the square wave's duty cycle. Can be either a float or another waveform orInstrument
. Default is 0.5.
Sawtooth(amplitude, width, static)
width
: width of the rising ramp as a proportion of the total cycle of the sawtooth wave.
Noise(amplitude, static)
Envelope(attack, decay, sustain, release, static)
attack
: sets the time it takes for the signal to rise from an amplitude of 0 to full amplitude. Default is 0.decay
: sets the time it takes for the signal to fall from full amplitude to the sustain level.sustain
: sets the amplitude of the wave for the time the key is held.release
: sets the time it takes for the sound to decay from the sustain level to an amplitude of 0 when the key is released.
Vibrato(osc, amount, static)
osc
: sets the rate at which the frequency oscillates. Default is 0.25.amount
: sets the amount of variation of frequency. Default is 1.
FreqSweep(toFreq, time)
toFreq
: the destination frequency.time
: the amount of time in which the wave's frequency should reach the destination frequency.
NOTE: The compiler will ignore any tabs or newlines. Spaces however make a difference in syntax, unless they're inside brackets.
Statements are not case sensitive.
- The
CREATE
statement is used to create instances of any class. - Optionally, a
WITH
clause can be added to pass arguments to the class constructor. Example:CREATE Instrument AS myInstrument WITH ( mySquare = Square(), myNoise = Noise() )
- The Python equivalent of the snippet above would be:
myInstrument = Instrument( mySquare = Square(), myNoise = Noise() )
- Assigns values to variables or properties of objects.
- Example:
SET duty OF myInstrument.mySquare TO 0.3
- The Python equivalent of the snippet above would be:
myInstrument.mySquare.duty = 0.3
- Plays or stops frequencies on a given channel id.
- The frequency can be:
- A number, in which case it will be interpreted as a value in Hertz;
- A note (example:
NOTE c4 CHANNEL 1 ON
). Notes are not case sensitive.
- The channel id can be anywhere in the range 0-15;
- The status can assume any value that is considered
True
, including language specific values such as ON and OFF (case insensitive). - An optional
USING
clause can be added, to specify which instrument to use. If not specified, the synthetizer will use the default instrument. Example:NOTE C4 CHANNEL 3 ON USING myInstrument
- Optionally, a
WITH
clause can be added to pass arguments to thenote
method:velocity
: relative volume of the note. Can be anywhere in the range 0-512. Default is 512.delay
: amount of time (in seconds) to wait after the note started playing. Default is 0.
- Example:
NOTE C4 CHANNEL 2 ON USING myInstrument WITH ( velocity = 128, delay = 1.5 ) NOTE C4 CHANNEL 2 OFF
- You can use SynthScript's Python API to do the same operation. The
note
method is composed like this:Arguments in angular brackets are optional.synth.note( frequency, channel, status, <instrument>, <velocity>, <delay> )
- Varies the pitch of all notes in a given channel.
- The channel id can be anywhere in the range 0-15;
- The amount can be anywhere in the range -8192 to 8192;
- Optionally, a
WITH
clause can be added to pass arguments to thepitchBend
method:delay
: amount of time (in seconds) to wait after the pitch bending has been applied. Default is 0.
- Example:
PITCHBEND CHANNEL 2 BY -123 WITH ( delay = 0.25 ) PITCHBEND CHANNEL 2 BY -292
- You can use SynthScript's Python API to do the same operation. The
pitchBend
method is composed like this:Arguments in angular brackets are optional.synth.pitchBend(amount, channel, <delay>)
- Waits a certain amount of time (in milliseconds)
- Example:
WAIT 500
- Creates an
Instrument
and sets it as default. - Example:
DEFAULT ( mySquare = Square( duty = 0.8 ) )
- The Python equivalent of the snippet above would be:
synth.defaultInstrument = Instrument( mySquare = Square( duty = 0.8 ) )
- Defines a callable segment of code. Equivalent of a Python function.
- Example:
DEFINE shortNote NOTE A4 CHANNEL 1 ON WITH ( delay = 1 ) NOTE A4 CHANNEL 1 OFF WAIT 1000 END
- Plays a defined section, a
Midi
, or a pygameSound
object. - Optionally, a
WITH
clause can be added to pass arguments to theplay
method:times
: amount of times the object will be played. Default is 1.blocking
: sets whether the method should wait until the end of the playback (True) or not (False). Default is True.- Example:
PLAY shortNote WITH ( times = 2 )
- You can use SynthScript's Python API to do the same operation. The
play
method is composed like this:Arguments in angular brackets are optional.synth.play(playable, <times>, <blocking>)