BoxyLady user manual

Choosing instruments and other settings

The instructions below assume that notes mode has been entered as explained previously.

Before musical notes can be generated, tempo, volume, and instruments should be selected with the following commands.

#SLOT: chooses SLOT as the currently selected instrument. Should not be issued within global. The implementation may choose to ignore this or raise an error.

Two types of instruments are possible. If instrument is specified as a slot containing sample data then this is rescaled when musical notes are generated according to the selected pitch. This normally works well but for certain types of sample interference effects may be audible which can be annoying, although often can be removed with a low-pass filter. Using instrument samples with a high resolution (much higher than the normal 44.1 kHz) alleviates this problem mostly.

Advanced use: Definitions created by def can also be used as instruments. In this case, the definition is called in sample (outer) mode. It is the responsibility of this "macro" to ensure that on its completion, a slot named instrument containing music data exists. Frequencies specified during voice synthesis should as usual assume a "standard" note of 440 Hz or as desired. The actual frequency generated by synth can be adjusted so that the correct note pitch is generated by setting pitch_adjust(T) in synth mode. The instrument slot can be created at the same sample rate as the final output file, as no rescaling is performed. Thus interference effects are not a problem. Nevertheless, the sample length cannot be guaranteed to be a multiple of the wavelengths synthesised, therefore it is a good idea to make the sample length at least as long as the largest note likely to be generated from it, and avoid looping the sample.

As an alternative to create(), the command instrument() can be used instead in this case. The instrument slot is automatically created with a length equal to the current note length. The same caveats about sample length as above still apply if effects such as pitch bends are applied. See also caveats at outer().

Slurs and pitch bends do not work with this.

rel(NOTE): Specifies that future notes will be relative to NOTE (in pitch notation), which is given as an absolute pitch (thus typically requiring several ' marks as the parser's default pitch is rather low. Does not generate notes itself.

octave(X): As above, but sets the octave level alone. X is a number.

tempo(TEMPO): Specifies the tempo, in crotchets/quarter notes (of duration "4") per minute.

tempo(rel=D): Specifies that the current note duration will be in future equivalent to D.

tempo(f=X): Specifies tempo as a fraction X of the curent tempo.

tempo_mode(MODE): If MODE=tempo, note durations are specified in the normal way. If MODE=time, note durations are given as decimal fractions of seconds instead (in which case rall and similar have no effect).

D_random(min=MIN max=MAX): Selects a random note length (not required to be integer) between MIN and MAX, where MIN and MAX are fraction denominators of a semibreve (not seconds).

amp(VOL): Specifies overall volume of subsequent notes generated (0-1 typical range). Volume perception is approximately logarithmic with amplitude, so small volumes such as 0.01 are not uncommon.

amp2(VOL): Acts multiplicatively in conjunction with amp. Can be useful to avoid having to vary several amp commands to affect overall volume. Any value can be specified, including negative or >1. The default is 1.

amp(f=X) amp2(f=X): Specifies volume as a multiplication factor of the previous volume.

amp_random(min=MIN max=MAX): Selects a random volume from within the range MIN to MAX (logarithmically).

amp_adjust(power=P standard=NOTE): If P is non zero (range of 0.0 to 1.0 is allowed), then higher pitch notes are automatically adjusted with decreased amplitude according to the specified power law. P=0.5 maintains constant power output across pitches for a given waveform; P=0.0 maintains constant amplitude. NOTE is optional as an absolute (not relative) pitch. If specified, it denotes the pitch where the adjustment has no overall affect. By default, this is a''''.

amp_adjust(off): Turns off amplitude adjustment.

Other note settings

stereo(L R): Sets the stereo position of subsequent notes. Acts multiplicatively with amp. Stereo can be turned off with stereo(off) and the channels reversed with stereo(swap).

stereo_random(left=L right=R): Stereo position is selected within the range given by L to R, which can range from -1 (full left) to +1 (full right).

envelope(PARAMETER LIST) or env(...): Defines an envelope to apply to subsequent notes. This is the correct way to apply an envelope to apply to "instrument" patches, rather than apply to the patch directly in sample mode (which will have strange effects if the sample loops).

env_adjust(BOOL): Allows notes (without reverb) to have their envelopes individually adjusted such that the final FADE phase takes place at the end of the note, provided it is long enough. This is carried out by changing the length of the SUSTAIN phase to fit, subject to a minimum length of zero. The SUSTAIN phase is stretched indefinitely for any notes in the middle of a slur. Note that even in a three-parameter envelope, the last parameter is always the FADE phase length.

tremolo(FREQ AMP): Applies tremolo (amplitude modulation) to subsequent notes with frequency FREQ. AMP in the range 0-1 is valid.

staccato(FRAC): Specifies the proportion of each note to actually be sounded, so as to avoid having to write articulations on each of a series of notes and allowing for other fractions than those allowed by articulation marks. Values in the range 0-1 are usual. Default value is 1. Values in excess of 1 will cause notes to overlap.

rev(X): X is a Boolean value which specifies whether reverberation should occur. When set, notes play to their end, irrespective of the specified note duration.

D_rev(NUM DENOM) D_play(NUM): As an alternative to rev(), an explicit length (in the same format as D(...)) can be given to subsequent notes. This does not affect the spacing of notes. D_rev(0) turns this functionality off.

precision(amp=AMP pitch=PITCH time=TIME) adds a natural sound by reducing the default accuracy of sound reproduction with random ranges specified to note amplitude (proportional), pitch (frequency ratio), and start time (seconds). Each parameter is optional and defaults to zero.

offset(TIME) shifts the start point of notes by a fixed specified period (seconds). Can be used with small negative values in conjunction with envelopes for an attack period before the beat.

If either of the above functions cause a note to be attempted to start before the beginning of the patch, these are ignored without generating an error.

vib(FREQ AMP OFFSET BEND BEND_T): Allows frequency modulation vibrato and pitch bend (for a specified duration) to be applied to subsequent notes. Three, four, or five parameters can be set.

bend(VAL): Sets the pitch bend alone for subsequent notes as a per-second multiplier. Slurs and note-specific effects take precedence.

bend(t=DURATION f=FACTOR): Sets the pitch bend as a duration DURATION over which time pitch increases by a factor FACTOR.

port(TIME): Sets a duration (in seconds) for which portamento is applied to slurred notes. This takes precedence over bend for slurred notes. Zero turns portamento off.

glide(BOOL): Sets a pitch glide to fill the whole time of subsequent notes. This takes precedence over bend and portamento. Pitch starts at the pitch of the previous note, and ends at the pitch of the current note, like a portamento.

scratch(with=WITH a=AMP bias=BIAS loop=LOOP): Performs a frequency modulation on subsequent notes where the frequency multiplier at time t is defined by WITH[a]*FACTOR+BIAS. Here WITH is a music sample with a single channel and sample rate equal to the sample being generated. For BIAS=1 and FACTOR small, a custom vibrato might be applied. For low BIAS or large FACTOR, this can cause the current instrument sample to even play *backwards*, in which case it loops from the end if it hits the beginning. If WITH is shorter than the current instrument, it loops as necessary if LOOP is TRUE. This function can be used in conjunction with other pitch bending functions. scratch(off) disables frequency modulation.

arp(DELAY): Normally, notes in a chords context begin simultaneously. Here, notes are delayed by DELAY (s) to provide an arpeggio effect.

articulations(...): Alters the system of articulations that can be applied to notes, thus altering the notation system again. This is described on a separate page here. Articulations take precedence over more general context settings.

beats(...): Allows rhythmic application of articulations. This is also described on the articulations page. The articulations applied by beats() take precedence over more general context settings, but can be overriden by specifically marking notes with articulations.

ignore_pitch(BOOL): When set, musical notes (generated by issuing note names) each have the pitch of the previous note, rather than reflecting the note specified. (Useful for sequences of notes reused as rhythms.)

post_process(SLOT): When given a slot name, allows post-processing of generated notes before they are overlaid on the current sample, when reverberation is not set. Sample Mode is called for SLOT and access to the note generated is available through a temporary slot named note. post_process(off) disables this functionality. Post-process cannot make notes longer, but it can make them shorter. Because the note is first copied to a temporary slot, this is slower than direct generation of music. post_process() does not work with slurs.

Tune settings

silence(T): Inserts a period of silence (does not actually mute other sound) of length T seconds. In chords mode, ensures the context is of at least length T.

transpose(NOTE): Normally, standard pitch corresponds to the note a''''. Music written at standard pitch now be played back at pitch NOTE. After tranpose() operations, it is likely that rel() will need to be re-specified, but not always.

transpose(Hz=FREQ): Specifies pitch scaling absolutely. FREQ=440 is defined as standard pitch.

transpose(f=FACTOR): All pitches are multiplied by FACTOR in relation to their previous value.

transpose(rel=NOTE): The pitch NOTE is now defined as the absolute pitch of the last note generated. Useful for chords libraries.

transpose_random(min=MIN max=MAX): Selects a pitch scaling at random within the range MIN to MAX, given in Hz.



gamut(...): These functions alter the tuning system, and in the latter case, the notation system. They are described on a separate page here.

rall(t=DURATION f=FACTOR): Initiates a rallentando (gradual slowing) in the current context, or alternatively, an accellerando. The tempo is slowed to a factor FACTOR of its starting value, over a time period of DURATION. FACTOR can be > 1 for an accellerando, or < 1 for a rallentando. A value of 0 will generate an error. rall(off) cancels any ongoing rall.

cresc(t=DURATION f=FACTOR): Initiates a crescendo (gradual loudening) in the current context, or alternatively, a diminuendo. The volume is amended to a factor FACTOR of its starting value (can be specified like any volume), over a time period of DURATION. As above, this value can be above or below 1, but not zero, and cresc(off) cancels the current settings.

pan(t=DURATION f=FACTOR): As above, but acts as a crescendo and balancing decrescendo on opposite channels, affecting the current stereo setting rather than current volume. (This does cause a change in volume in mono samples.)

salendo(t=DURATION f=FACTOR): The counterpart of crescendo and rallentando, but for pitch. Initiates a gradual rising or falling in pitch in the current context. The tranposition factor is amended by FACTOR over time period DURATION. Again, this cannot be a zero value, and salendo(off) cancels current settings. This does not cause each note to change in pitch during its play duration: to do this, use bend().

staccando(t=DURATION f=FACTOR): As above, but for staccato! FACTOR less than one shortens notes over time. This does not affect the spacing of notes.


rem("TEXT") and echo("TEXT") also work in notes mode.

! gives a brief "hash mark" to the console to show progress.

show_state(): Shows all current settings applicable to the context not accessible through various list() functions.

bar_check(BOOL) turns bar checking on and off. It defaults to off.

Control and flow

Definitions created by def are included in the current by \SLOT. These calls can be nested. They do not create a new context automatically.

def() also works in notes mode.

Other generated sequences or loaded patches can also be included using \SLOT. The current stereo and amplitude are applied to them, and they fill time in the same way as notes do respecting their t-time and p-time settings.

N(X): Sets the current pitch (relative to the previous pitch) without generating any music or causing any other side effects. X is a normal musical note.

S(STEP ACC OCT) S(STEP ACC) S(STEP) S(): As above, but the new note is selected as on offset from the previous one in terms of scale steps STEP (i.e. the sequence of note names), accidentals ACC, and octaves OCT. If no parameters are specifed, a single upward step is made.

C(X SLOT): Equivalent to N(X) \SLOT. SLOT is the name of a definition, without a leading backslash, and X is a normal musical note. For use in chord libraries, ottavo effects, and similar.

unfold(n=COUNT music={MUSIC}): Repeats MUSIC, COUNT times. The delimeters {} can also be one of (), <> or []. () does not create a new context for each separate repeat.

fill(t=TIME music={MUSIC}): Similar to the above, but a time period TIME is filled with music, instead of a specified number of repeats.

oneof({A} {B} {C} {...}): One of A, B, C... is chosen, at random. The delimeters {} can also be one of (), <> or []. () does not create a new context. Delimeters can be omitted, in which case () is assumed.

shuffle(n=COUNT replace=BOOL from({A} {B} {C} {...})): random music is repeatedly chosen COUNT times from the list at from(), syntax of which follows that for oneof(). If BOOL is omitted or false, each of A, B, C... is only used once. In this case, if COUNT is omitted, the whole list is shuffled.

foreach(var(V) in((A) B (C D) ...) do{MUSIC}): For each music expression A, B, C, ..., given in the in block, a macro V is defined, and the music expression MUSIC evaluated (which usually will refer to V). V must not already exist. Each in definition must use () as delimeters if more than a single token. The delimeters {} can also be one of (), <> or []. () does not create a new context for each separate repeat.

flags(...): Also works in notes mode, on the current sample only. This is unlikely to be necessary but allows access to the gate setting, e.g. flags(gate=F).


outer(COMMANDS) calls the outer, sample mode and performs the commands COMMANDS. For advanced use only. Attempting to use this to modify the sample currently being written will lead to unpredictable results and probably indicates bad style. Using outer to delete a slot currently in use will generate an error.

context_mode(chords) context_mode(tune): Manually switch between chords and tune mode, without creating a new context. (Note that the time pointer is advanced after each note in tune mode.)