Status of this page

This page provides an alternative view of the sfz format documentation provided by rgc:audio here. As such, it is unofficial and all the mistakes in this are mine. Please drop me a note (address at the bottom) if you find anything hard to follow - or wrong!

For a more official (read authorised, whatever that means!) look into the rgc:audio synths, sfz and more, check Simon Cann's book, Cakewalk Synthesizers.

Wherever possible, the general layout of this page is to cover MIDI-related values then player/internal values. The MIDI values are covered in message number order.

sfz format - the model player

Overview

The player is a sample-based wavetable synthesiser with unlimited polyphony and an unlimited number of layers per voice. For each layer, the sample can be repitched and passed through a filter unit, an amplifier, an EQ and a pair of effects sends. The layers are processed independently (sharing the effects) then mixed down to the player outputs. All of this is controlled through instructions in a text file.

The model in more detail

Any number of layers can be triggered by a MIDI Note On or Continuous Controller (CC) event. Which layer is triggered depends on a large number of parameters.

The player can delay playing a layer:

The part of the sample to play and how the sample should be looped, if at all, can be controlled for the layer.

The player can alter the pitch of a layer by a fixed amount, by an amount based on the triggering event, by the Pitch Wheel, by a random amount and by amounts from an envelope generator and a low frequency oscillator.

The player can apply a resonant filter to the signal generated by the layer, with the filter's cutoff frequency given as a fixed value, adjusted based on the triggering event and from MIDI realtime controls, and further adjusted by a random amount and by amounts from an envelope generator and a low frequency oscillator.

The signal passes through an amplifier, with the gain set to a fixed value, adjusted based on the triggering event, by the time since the triggering event and under MIDI CC-control, and further adjusted by a random amount and by amounts from an envelope generator and a low frequency oscillator. The player can also effect cross-fades between one voice layer and another and allows the signal's stereo image to be altered.

The signal can then pass through a three-band parametric EQ where any fixed settings can be adjusted by an amount based on the triggering Note On event velocity and from a MIDI CC.

The final, mixed signal for a (stereo) output can also be sent to two player-dependent effects. (Generally, these are expected to be reverb and chorus units.)

The following table summarises the control adjustments available, where more than a fixed setting is possible:

Setting

Adjustment

MIDI

Internal

Note #

Velocity

Poly Aft

MIDI CC#

Chan Aft

Pitch Wheel

Random Value

Envelope Gen

Low Freq Osc

Delay

Y

Y

Offset

Y

Y

Pitch

Y

Y

Y

Y

Y

Y

Filter

Y

Y

Y

Y

Y

Y

Y

Y

Amplifier Gain

Y

Y

Y

Y

Y

Y

EQ

Y

Y

Note number and velocity tracking only occurs for Note On trigger events. Random adjustments happen at the time of the trigger event. All the other adjustments are in real-time (unless stated otherwise in the detail).

The current sfz.exe implementation from rgc:audio enhances the above with some unofficial additional controls, through additional MIDI CC numbers.

Everything you wanted to know about the model player

This section tells you how to set up the player to play samples the way you want it to. It starts with a description of the sfz file format itself.

To find stuff quickly, I suggested you use the links in the previous section as a table of contents.

File format and content

sfz format files are text files. It is a good idea to have the file's name end with ".sfz" so you know what it is when you look at it.

Comments can be included in the file - all text after a "/" on the same line is a comment and ignored.

Any unrecognised file content is also ignored.

Opcodes

The instructions to the player on when and how to play a particular sample are given with "opcodes". These are short names for the various settings and controls the model player provides. I have highlighted all the opcodes so you can find them easily.

Note that where MIDI continuous controllers can be used, there is generally one opcode per CC number. Rather than list all 128 (0 to 127) opcodes, the CC number has been replaced with "#". Use the appropriate number when you write the opcode in the sfz format file in place of the #.

The current sfz.exe implementation from rgc:audio extends the CC number range with some unofficial additional controls.

Opcodes and values

Opcodes are recognised by being separated from any preceding content (by space, tab, new line) and followed immediately by "=" (equals).

Values are taken as everything following the "=" after an opcode up to the separator before the next opcode or the next header or end of file. There should be no spaces between the "=" and the value. There should be no "=" in filenames. Further parsing details are implementation-dependent.

A later opcode takes priority over previous settings.

Headers

The text "<group>" and "<region>" separate parts of the file. These are referred to as group and region headers.

A "group section" is all the opcodes between one group header and the next header.

All the opcodes in the most recent group section, if any, plus all the opcodes between one region header and the next header or end of file, form the definition of that region. If an opcode occurs in a region and the same opcode was specified in the group section, the value in the region is used and the value in the group section is ignored.

The key opcode is treated as the three separate opcodes lokey, hikey and pitch_keycenter for this.

A region is what forms a layer within a voice when played. Mostly this document talks about layers. Even when maybe it should say region.

Units

Unless otherwise stated:

The trigger event

An event is any incoming MIDI message received by the player. A trigger event is an event that causes a layer to be selected for playing. The process of selecting a layer to play takes place whenever a MIDI Note On or CC event occurs.

While no other kinds of MIDI event trigger the selection process, other values can be used to choose between different layers: other notes, other MIDI controls and internal settings.

Remember, only one event can be happening at any one time. Trying to have a single layer triggered by different kinds of event will not work.

MIDI Note On trigger event

When the trigger event is a MIDI Note On, the components of the MIDI Note On event are available (channel, note number, velocity) for layer selection.

The player will select the layer only if each of the event's component values lies within a given range. The default lower limit is the lowest value allowed. The default upper limit is the highest value allowed. (In other words, the player defaults to selecting the layer unless told otherwise.)

To prevent the player even trying to match the components of a Note On event for a layer, set the note number upper limit to -1. If you want the layer triggered by a MIDI CC event, you must do this.

The ranges are as follows:

Component

Allowed range

Lower limit

Upper limit

Channel

1 to 16

lochan

hichan

Note number

0 to 127
C-1 to G9

lokey

hikey

Velocity

1 to 127

lovel

hivel

key sets lokey, hikey and pitch_keycenter (see here) to the same note number.

MIDI CC trigger event

When the trigger event is a MIDI CC, the components of the MIDI CC event are available (channel, CC number, CC value) for layer selection. The CC number of the trigger event must be a specific number (0 to 127). There is no way to trigger a layer based on a range of CC numbers.

The player will select the layer only if the channel and CC value components lie within given ranges. The default lower setting is the lowest value allowed. The default upper setting for channel is the highest value allowed; for the CC value, the default is -1. (In other words, the default is to disable triggering the layer by CC event.)

To enable a CC event to trigger a layer, set the CC value upper limit to zero or more and disable Note On triggering.

The ranges are as follows:

Component

Allowed range

Lower limit

Upper limit

Channel

1 to 16

lochan

hichan

CC value

0 to 127

on_locc#

on_hicc#

The # in the CC value opcodes should be replaced with the CC number to be used as the trigger event (0 to 127).

The current sfz.exe implementation from rgc:audio extends this range with some unofficial additional MIDI CCs. However, these don't appear to work as trigger events (as the event is not really a MIDI CC, I guess).

Beyond the trigger event - further layer selection

The player can use the settings of various controls at the time of the trigger event to choose whether to select a particular layer to play.

When selecting based on MIDI event information, each MIDI channel remembers events separately and the values checked for will be those of the same channel as the trigger event (Note On or CC).

The layer will be selected to play only if the trigger event and the settings of all the controls "match" the values given. How the layer sounds is then controlled as described further down this page.

The following sections describe the selection controls available.

Other notes

The player can use whether other notes are currently playing or not to select the layer. The valid range for note numbers is 0 to 127 or the equivalent note names, C-1 to G9.

The player can be told about a range of notes that are to be used as "switches" for the layer (sw_lokey (default 0) to sw_hikey (default 127)). Unless a switch is checked, its state is ignored when deciding whether or not to play the layer.

The player can be told to only select the layer if the indicated switch note:

was the most recent (whether it's now down or not)

sw_last

is still down

sw_down

is not down

sw_up

Regardless of the range of switch notes (and again, with the player not caring about the condition unless it's mentioned), the player can be told to only select the layer if the most recent (preceding) note:

matches

sw_previous

is still down

trigger=legato

is not down

trigger=first

Other MIDI controls

The player can use the settings of other, non-note MIDI events to choose whether or not to select the layer. As with all layer selection, the player checks the settings at the time of the trigger event. (Currently, the Program Change control cannot be used.)

The player will select the layer only if all the settings lie within given ranges. The default lower setting is the lowest value allowed. The default upper setting is the highest value allowed. (In other words, the default is to select the layer.)

Control

Range Allowed

Lower limit

Upper limit

Polyphonic aftertouch

0 to 127

lopolyaft

hipolyaft

MIDI CC #

0 to 127

locc#

hicc#

Channel aftertouch

0 to 127

lochanaft

hichanaft

Pitch wheel

-8192 to 8191

lobend

hibend

The # in MIDI CC opcodes should be replaced with the CC number to be used (0 to 127).

The current sfz.exe implementation from rgc:audio extends the CC number range with some unofficial additional controls. These cannot be used for layer selection - use the appropriate real opcode.

Player state

For the last part of the selection process, the player can be told to select the layer based on certain internal control settings.

There are two ranged settings:

Control

Range Allowed

Lower limit

Upper limit

Random number

0 to 1

lorand

hirand

Beats per minute

0 to 500

lobpm*

hibpm*

In both cases above, the player checks that the setting is equal to or above the lower limit and below (but not equal to) the upper limit. The same random number is used when considering all the layers for a particular trigger event.

Each layer can also be given a position within a sequence (seq_position) and only selected when an internal sequence counter matches. If no position is given (i.e. only the length is given), the layer will not match. The counter starts at 1 and goes up by one each time the layer would have been selected if the sequencer counter wasn't being used. It gets reset to one when it reaches the seq_length for the layer.

When to play

The time at which playback starts is termed the trigger point. The trigger point is when all the EG and LFO processing begins. The normal trigger point is the time when the trigger event (i.e. Note On or MIDI CC) occurs. However this can be delayed:

If the trigger point hasn't been reached before EG release processing is triggered, the layer doesn't play at all (no EG or LFO processing occurs).

Playback duration

There are two factors that affect how long a note lasts: how much sound there is to play and when the amplifier gain EG finishes. The player plays what it can until the amplifier gain EG returns to zero or there is no more sound.

EG release processing

The envelope generators are described in detail further on. This section explains how to trigger EG release processing. There are two ways:

  1. If the layer was triggered by a Note On event (and not delayed until Note Off by trigger=release), a matching Note Off event will trigger EG release processing.
  2. If a layer is triggered in a group that this layer is stopped by, depending on the off_mode:

    start release processing - EGs levels return to zero in their own release time

    off_mode=normal

    stop playback - no EG Release processing takes place (default)

    off_mode=fast

Exclusive groups

An exclusive group is commonly a group of trigger events that cause any layer triggered to be muted when another layer in the group is triggered. In sfz format, a more flexible approach is taken.

Any layer to be muted is labelled with off_by (0 to 4Gb).

Any layer to cause muting is labelled with group (0 to 4Gb). Triggering such a layer causes any layer with a different trigger event and a matching, non-zero off_by value to be muted or released.

Any number of layers can have the same group number. Any number of layers can be sensitive to the same group number. A layer need not have a group number to be sensitive to being stopped and vice versa.

What to play

The sample

The player must be told where to find the sample file (i.e. the location), using sample.

The location can be given as a "relative path". The player should use the location of the loaded sfz format file as the starting point for following the path - thus a simple file name will be found in the same directory (folder) as the sfz format file.

Sample files can be either Microsoft Wave Audio (".wav") files or Ogg Vorbis compressed (".ogg") files.

A region with no sample specified is ignored. (If you want triggering one layer to stop another layer playing - using group/off_by, see elsewhere - but you don't want it to sound, specify any sample and set the end position to -1.)

Start position or "Offset"

The player takes the start of the file as the first sample position.

This start position can be moved a fixed number of samples further on, using offset (0 to 4Gb).

Further MIDI CC-controlled and random offsets can then be applied.

If the start position ends up beyond the end position, the sample will not play.

End position

The player takes the end of the file as the last sample position.

This end position can be moved before the end of file, using end (0 to 4Gb, or -1 meaning the sample will not play), which gives the offset from the start of the file to the last sample to play.

Playing the whole sample repeatedly

Normally, playback begins at the start position and plays through to the end position and then stops (unless the amplitude EG is shorter than this time).

The sample player can be told to play the sample (from start offset to end) a fixed number of times, ignoring Note Off and any loop information, using count (0 to 4Gb times).

("count=1" is very similar to "loop_mode=one_shot".)

Playing part of the sample repeatedly

The player can be told that a certain region of the file can be looped: either using loop_start and loop_end (both range 0 to 4Gb) to specify the sample numbers to start and end looping or - if not overriden by these opcodes - by information embedded in the file (ACIDized loops).

The player can loop the sample - that is, play from start offset to the loop's end, then from the loop's start through to loop's end point repeatedly - in one of two modes:

loop until the amplitude EG reaches zero; default if loop points defined

loop_mode=loop_continuous

loop until Release and then play through to the end point or amplitude EG reaching zero

loop_mode=loop_sustain

Where one of the above opcodes is used but no loop information is present (either specified in the sfz file or in the sample), the start offset and end of the sample are used as the loop start and end (unless end is given, in which case the sample isn't looped).

The player can also be told to turn off looping when loop points are defined (loop_mode=no_loop; default if no loop points defined).

Playback Pitch

The player can adjust the pitch of the layer by a fixed amount:

a number of semitones between -127 and 127

transpose

a number of cents between -100 and 100

tune

Together these allow the perceived pitch of a sample to be matched to a reference pitch.

The pitch can also be adjusted by:

Filter

The player passes the sound - generated by playing the layer's sample and adjusting the pitch - through an optional filter stage. The filter type is set using fil_type, with values as follows:

Filter type

Value

one-pole low pass filter (6dB/octave)

lpf_1p

one-pole high pass filter (6dB/octave)

hpf_1p

two-pole low pass filter (12dB/octave) (default)

lpf_2p

two-pole high pass filter (12dB/octave)

hpf_2p

two-pole band pass filter (12dB/octave)

bpf_2p

two-pole band rejection filter (12dB/octave)

brf_2p

Filter cutoff frequency

The player can set and adjust the frequency of the filter cutoff. There are a number of ways of controlling this adjustment that add together:

Amplifier

The player passes the (possibly filtered) sound through an amplifier stage.

If the layer was triggered by a Note On event...

By default, the player determines the initial gain from the following calculation:
-20 * log(127^2 / Velocity^2)
which is then scaled according to the velocity tracking.

For example, with 100% velocity tracking, this gives about -84dB of gain for a note with velocity 1, -13dB at velocity 64, -4dB at velocity 100 - and, of course 0dB at velocity 127. -10% velocity tracking would give 8.4dB, 1.3dB, 0.4dB and 0dB for the same velocities.

If the default velocity response curve does not suit and velocity tracking doesn't help, amp_velcurve_# allows specifying the gain at specific velocities (replace # in the opcode by the velocity number, 1 to 127, values range from 0 to 1, with velocity 127 defaulting to 1 and missing opcodes assigned values evenly between those given). A value of "1" applies 0dB of attenuation. A value of "0.5" applies 6dB of attenuation, halving the volume. A value of "0" applies infinite attenuation, resulting in silence.

For non-normalised multi-samples, assuming the layers are trigger in loudness order, the following can be used to set the other layers up appropriately:

  1. Determine the layer RMS volumes in decibels (I use Voxengo's Leveler tool).
  2. For each layer below the loudest, determine the difference in decibels -- ddd.
  3. Calculate the equivalent velocity:
    sqrt( 127^2 / arclog( ddd / 20 ) )
    and call this vvv.
  4. Tag each layer with "lovel=xxx", "hivel=vvv" and "amp_velcurve_vvv=1", where xxx is one more than the lower layer's hivel, as usual.

I have written a small utility to make this easier: VelLeveler.

A more complex approach is needed where, as can be the case with natural instruments, the "hardest hit" does not achieve the loudest volume (perhaps due to a damping action).

Appropriate "amp_velcurve_vvv=lll" velocities (vvv) and levels (lll) can be chosen to give a smooth, natural and realistic response. Each layer should be given a pair of response curve points for the lower and upper ends of the velocity range (actually, the lower vvv being the next lower velocity layer's hivel value rather than this layer's lovel value). If the lower layer is quieter, set the upper lll to 1 and the lower to achieve sufficient attenuation to reduce this layer by the difference in the two layer's levels (see below). If the lower layer is louder, set the lower lll to 1, use volume to provide gain equivalent to the difference in levels and set the upper lll to bring the maximum level back down by the same amount.

To calculate the lll value, use the following formula:
10^(difference/20)
remembering the "difference" should be negative if you are following this scheme.

You are not limited to two points per layer, of course - more complex curves can be drawn.

If the layer was delayed until Note Off, a further gain reduction in decibels per second since Note On is applied, given by rt_decay (0 to 200dB/s, default 0). This is in addition to any gain adjustment that would apply had the layer been triggered by the Note On rather than Note Off.

Otherwise the initial gain is 0dB.

Further gain adjustments can be made by:

The overall gain must remain in the range -144 to 6 decibels.

When the amplitude EG returns to zero, the layer stops playing.

Cross-fading layers

In addition to the above settings, the player can cross-fade a layer based on MIDI controls. The range of the fade in and fade out for each control can be set as can the choice of curve.

As the setting applies to a single layer, cross-fade is possibly not an obvious term. The idea is to set up complementary fades on two layers to effect the cross-fade.

The volume of the layer will be zero below the fade in lower limit. There will be no further attenuation applied above the fade in upper limit and below the fade out lower limit. The volume of the layer will be zero above the fade out upper limit.

The default for the fade in range is 0; the default for the fade out range is 127 (thus, there is no fading by default for any control).

The curve can be (to quote the official sfz format page):

gain
Linear gain crossfade. This setting is best when crossfading phase-aligned material. Linear gain crossfades keep constant amplitude during the crossfade, preventing clipping.
power
Equal-power RMS crossfade. This setting works better to mix very different material, as a constant power level is kept during the crossfade.

Control

Fade In Range

Fade Out Range

Curve

Note number

xfin_lokey
xfin_hikey

xfout_lokey
xfout_hikey

xf_keycurve

Velocity

xfin_lovel
xfin_hivel

xfout_lovel
xfout_hivel

xf_velcurve

MIDI CC#

xfin_locc#
xfin_hicc#

xfout_locc#
xfout_hicc#

xf_cccurve

All cross-fading happens in real-time, with the proviso that the note number and velocity are static!

The # in the CC opcodes should be replaced with the CC number to be used. The same curve is used for any CC cross-fade on this layer.

The current sfz.exe implementation from rgc:audio extends the CC number range with some unofficial additional controls.

Stereo position

The amplifier also has controls to adjust the stereo position of the layer.

The current sfz.exe implementation from rgc:audio adds controls to many opcodes with some unofficial additional MIDI CC numbers.

The gain for each stereo output can be adjusted, effectively fading across from left to right, using pan:

left channel

right channel

pan

fully left silent -100
same gain as right same gain as left 0
silent fully right 100

This applies equally to mono samples (which are played through both channels) and stereo samples.

For stereo samples only:

The stereo "width" of the sample can be reduced and reversed by fading the left channel across to the right output and vice versa, using width, with values in the range 100 to -100, meaning:

full stereo, left is left, right is right (default) 100
stereo played as mono 0
full stereo, left on right, right on left -100

The position of the resulting image can then be adjusted, using using position, from -100 (fully left) through 0 (center) to 100 (fully right).

Equaliser

The player passes the layer's amplified sound through a three-band parametric equaliser. In addition to fixed settings, the controls can all be adjusted by MIDI CC and the frequency and gain are velocity-sensitive. By default, the response is flat, having no effect on the signal. The controls are:

Control

Fixed

Velocity-sensitive depth

CC controllable depth

Frequency - center frequency for the band in Hz
(fixed: 0 to 30000, defaults as shown; adjustable: -30000 to 30000, default 0)

eq1_freq (50Hz),
eq2_freq (500Hz),
eq3_freq (5000Hz)

eq1_vel2freq,
eq2_vel2freq,
eq3_vel2freq

eq1_freqcc#,
eq2_freqcc#,
eq3_freqcc#

Bandwidth in octaves
(fixed: 0.001 to 4, default 1; CC: -4 to 4, default 1)

eq1_bw,
eq2_bw,
eq3_bw

-

eq1_bwcc#,
eq2_bwcc#,
eq3_bwcc#

Gain - center gain of the filter in decibels
(-96 to 24, default 0)

eq1_gain,
eq2_gain,
eq3_gain

eq1_vel2gain,
eq2_vel2gain,
eq3_vel2gain

eq1_gaincc#,
eq2_gaincc#,
eq3_gaincc#

# in the opcode should be replaced by the CC number being used.

The current sfz.exe implementation from rgc:audio extends the CC number range with some unofficial additional controls.

Effects sends

The player has two effects units and part of the signal can be sent to each, using effect1 and effect2 (0 to 100 percent, default 0).

See the note on implementation below for what the effects do in sfz. Other players may choose different effects, although that would cause playback to sound different, of course.

Player outputs

Each layer can be independently routed to one of the player's stereo outputs, using output (0 to 1024, default 0).

The current sfz.exe implementation from rgc:audio ignores the opcode for values it doesn't support (i.e. everything above 0 is routed to 0, the only output), although a more intelligent mapping down to the number of supported outputs could be provided by other players (e.g. modulo number of outs).

Adjusting the controls

As shown in the table near the beginning, there is a wealth of ways to adjust the player's controls. This section explains them and cross-references back to the appropriate control.

The current sfz.exe implementation from rgc:audio adds to the above with some unofficial additional controls.

MIDI Note On note number

If the layer was triggered by a Note On event, control adjustments can be made based on the MIDI note number. The adjustment is calculated by:
(note number - center) * depth
where "center" and "depth" amounts are given by the following opcodes, depending what control is being adjusted:

control

center

depth

depth default and range

Pitch

pitch_keycenter

pitch_keytrack

default: 100 cents (1 semitone); range -1200 to 1200 cents

Filter cutoff

fil_keycenter

fil_keytrack

default: 0; range 0 to 1200 cents

Amplifier gain

amp_keycenter

amp_keytrack

default: 0; range -96 to 12dB

"center" defaults to 60 (middle C, C4) with a range -127 to 127. The adjustment is applied to the layer once, at the time of the trigger event.

MIDI Note On velocity

If the region was triggered by a Note On event, the control adjustment can be made based on the velocity. The adjustment is calculated by:
(depth * velocity / 127)
where "depth" amounts are given by the following opcodes, depending what control is being adjusted:

control

depth

depth range

Pitch

pitch_veltrack

-9600 to 9600 cents

Filter cutoff

fil_veltrack

-9600 to 9600 cents

Amplifier gain

amp_veltrack

-100 to 100 percent

Equaliser

eqx_vel2xxx

See EQ

Envelope generators

xxx_vel2xxx

See EG

The default depth is always zero. The adjustment is applied to the layer once, at the time of the trigger event.

Polyphonic Aftertouch

Control adjustments can be made based on polyphonic aftertouch events. The initial adjustment is based on the most recent value received. This is then updated each time a polyphonic aftertouch event occurs, in real-time. The adjustment is calculated by:
(depth * value / 127)
where "depth" amounts are given by the following opcodes, depending what control is being adjusted:

control

depth

depth range

Filter cutoff

cutoff_polyaft

0 to 100

Low frequence oscillators

xxx_xxxpolyaft

See LFO

MIDI CC

Control adjustments can be made based on MIDI continuous controller events. The initial adjustment is based on the most recent value received. This is then updated each time a MIDI continuous controller event occurs, in real-time, except for delay and offset, which are only applied at the time of the triggering event. The adjustment is calculated by:
(depth times CC value / 127)
where "depth" amounts are given by the following opcodes, depending what control is being adjusted:

control

depth

depth range

Delay

delay_cc#

0 to 100 seconds

Offset

offset_cc#

0 to 4Gb

Filter cutoff

cutoff_cc#

-9600 to 9600 cents

Amplifier gain

gain_cc#

-144 to 48 dB

Amplifier gain EG

amp_xxxcc#

See EG

Equaliser

eqx_xxxcc#

See EQ

Low frequence oscillators

xxx_xxxcc#

See LFO

The default is zero in all cases.

# in the opcode should be replaced by the CC number being used.

The current sfz.exe implementation from rgc:audio extends the CC number range with some unofficial additional controls.

Channel Aftertouch

Control adjustments can be made based on channel aftertouch events. The initial adjustment is based on the most recent value received. This is then updated each time a channel aftertouch event occurs, in real-time. The adjustment is calculated by:
(depth * value / 127)
where "depth" amounts are given by the following opcodes, depending what control is being adjusted:

control

depth

depth range

Filter cutoff

cutoff_chanaft

0 to 100

Low frequence oscillators

xxx_xxxchanaft

See LFO

Pitch Wheel

The pitch wheel can be used to adjust playback pitch. The initial adjustment is based on the most recent value received. This is then updated each time a pitch wheel event occurs, in real-time. The adjustment is calculated by:
(depth * MIDI value / MIDI range)
where The MIDI range of the wheel used and "depth" depend on the MIDI value being above or below zero:

MIDI range

Depth

Default depth

above 0

8191

bend_up

200

below 0

-8192

bend_down

-200

The range of values for both opcodes is -9600 to 9600.

The "smoothness" of the pitch wheel can be set so that the pitch changes by a number of cents at a time, using the bend_step opcode, range 1 to 1200 cents, default 1.

Random Values

A random adjustment to a control can be made at the time of the triggering event. The random adjustment is added to the absolute control setting to get the setting for the layer. The depth of the adjustment can be set for each control.

Control

depth

Range

Delay

delay_random

0 to 100 seconds

Offset

offset_random

0 to 4Gb

Pitch

pitch_random

0 to 9600 cents

Filter Cutoff

fil_random

0 to 9600 cents

Amplifier Gain

amp_random

0 to 24 dB

The default depth is always zero.

Envelope Generators (EGs)

This section gives the full detail on the working of the envelope generators, including what opcodes are available. Note also the sections on EG release processing and when EG processing is triggered (the trigger point).

An envelope generator adjusts another control by an amount that varies over time through a single cycle, with a degree between zero and 100 percent of the EG's depth. In addition to "absolute" settings, the EG's controls can also respond to a variety of MIDI events (see tables above and, in detail, below).

Absolute time and percentage controls are in the range 0 to 100. Velocity-sensitive and CC-controlled time and percentage adjustments are in the range -100 to 100. Absolute, velocity-sensitive and CC-controlled depth control ranges depend on what is being controlled (pitch, filter cutoff frequency or amplifier gain).

Velocity is taken from the Note On event triggering the layer (and is only available if triggered by a Note On event). CC adjustments are made in realtime. The velocity and CC adjustments are added to the absolute control setting to get the current EG control setting.

All controls default to zero except the absolute sustain level, which defaults to 100%.

It's worth repeating: when the amp EG level reaches zero, playback (and all layer processing) stops.

Each EG has the following controls:

Control

Description

Pitch EG

Filter Cutoff EG

Amp EG

Delay time

Time after the trigger point before the attack begins

pitcheg_delay,
pitcheg_vel2delay

fileg_delay,
fileg_vel2delay

ampeg_delay,
ampeg_vel2delay,
ampeg_delaycc#

Start level

The percentage at which the attack begins

pitcheg_start

fileg_start

ampeg_start,
ampeg_startcc#

Attack time

The time taken to rise from the start level to 100%

pitcheg_attack,
pitcheg_vel2attack

fileg_attack,
fileg_vel2attack

ampeg_attack,
ampeg_vel2attack,
ampeg_attackcc#

Hold time

The time the 100% level is held

pitcheg_hold,
pitcheg_vel2hold

fileg_hold,
fileg_vel2hold

ampeg_hold,
ampeg_vel2hold,
ampeg_holdcc#

Decay time

The time taken to fall to the sustain level

pitcheg_decay,
pitcheg_vel2decay

fileg_decay,
fileg_vel2decay

ampeg_decay,
ampeg_vel2decay,
ampeg_decaycc#

Sustain level

The level held until the envelope is released

pitcheg_sustain,
pitcheg_vel2sustain

fileg_sustain,
fileg_vel2sustain

ampeg_sustain,
ampeg_vel2sustain,
ampeg_sustaincc#

Release time

The time taken to fall from the sustain level to zero after release

pitcheg_release,
pitcheg_vel2release

fileg_release,
fileg_vel2release

ampeg_release,
ampeg_vel2release,
ampeg_releasecc#

Depth

The depth of the pitch EG is in cents. Both absolute and velocity-sensitive controls have a range of -12000 to 12000 cents (10 octaves).

The depth of the filter cutoff EG is in cents. Both absolute and velocity-sensitive controls have a range of -12000 to 12000 cents (10 octaves).

The depth of the amplifier EG is from silence to no gain reduction. At 0%, the signal is muted. At 100% there is no reduction.

pitcheg_depth,
pitcheg_vel2depth

fileg_depth,
fileg_vel2depth

-

# in the opcode should be replaced by the CC number being used.

Low Frequency Oscillators (LFOs)

This section gives the full detail on the working of the low frequency oscillators, including what opcodes are available. Note also the section on when LFO processing is triggered (the trigger point).

A low frequency oscillator adjusts another control repetitively over time, running from -100% to 100% of the LFO's depth. The effect can begin after some interval then gradually rise from zero to full-scale over time. In addition to "absolute" values, the cycle time (frequency) and effect depth controls can be controlled in realtime by a selection of MIDI events.

Absolute time controls are in the range 0 to 100. Absolute frequency controls are in the range 0 to 200. Absolute depth is -1200 to 1200 cents, for pitch and filter cutoff, and -10 to 10 dB for amplifier gain.

Realtime-controllable frequency adjustments are in the range -200 to 200. Realtime-controllable depth adjustments have the same range as the absolute depth.

The realtime-controllable adjustments are all added to the absolute control setting to get the current LFO control setting.

All controls default to zero.

Each LFO has the following controls:

Control

Description

Pitch LFO

Filter Cutoff LFO

Amp LFO

Delay time

Time after the trigger point before the effect begins

pitchlfo_delay

fillfo_delay

amplfo_delay

Fade time

Time after the effect begins for the depth to be reached

pitchlfo_fade

fillfo_fade

amplfo_fade

Frequency

Number of cycles per second

pitchlfo_freq,
pitchlfo_freqpolyaft,
pitchlfo_freqcc#,
pitchlfo_freqchanaft

fillfo_freq,
fillfo_freqpolyaft,
fillfo_freqcc#,
fillfo_freqchanaft

amplfo_freq,
amplfo_freqpolyaft,
amplfo_freqcc#,
amplfo_freqchanaft

Depth

The depth of the pitch LFO is in cents. Both absolute and realtime controls have a range of -1200 to 1200 cents (1 octave).

The depth of the filter cutoff LFO is in cents. Both absolute and velocity-sensitive controls have a range of -1200 to 1200 cents (1 octave).

The depth of the amplifier LFO is in dB. Both absolute and velocity-sensitive controls have a range of -10 to 10 dB.

pitchlfo_depth,
pitchlfo_depthpolyaft,
pitchlfo_depthcc#,
pitchlfo_depthchanaft

fillfo_depth,
fillfo_depthpolyaft,
fillfo_depthcc#,
fillfo_depthchanaft

amplfo_depth,
amplfo_depthpolyaft,
amplfo_depthcc#,
amplfo_depthchanaft

# in the opcode should be replaced by the CC number being used.

sfz Implementation

rgc:audio's sfz sample player is here. The documentation takes the form of a FAQ, here.

In the sfz implementation, opcodes marked * in this document require that the player be running in a VSTi host, rather than standalone. Other players may or may not have this constraint.

Effect 1 in sfz is Reverb. CC12 controls the reverb size, CC91 controls the send amount.

Effect 2 in sfz is Chorus. CC93 controls the send amount.

If the sustain pedal is pressed (MIDI CC number 64 value is 64 or above), sfz does not process MIDI Note Off events until the pedal is released. All Note Off related processing happens at that point.

"Undocumented" features

sfz format is intended to be extensible by developers. To that end, there are a couple of features that sfz (the program) has that are not part of the official spec.

Finite Impulse Response filter unit

sfz contains a single (up to) 512-order FIR filter unit. This is performed using time-domain convolution between an impulse response sample and the output signal. The whole signal passes through the unit. The impulse response is set using impulse, which works like sample, see here. Unless this is specified, no convolution takes place. However long the impulse file, only the first 512 samples are used, which is sufficient for simulating filter effects (like the sound of a microphone or a speaker cabinet, maybe) but not for full-on cathedral-size reverb.

The depth of the effect can be controlled, using impulse_gain (-96dB to 48dB ????guess????, default 0).

Impulse sample files can be found in many places: noisevault is a good place to start. There's an entire thread on K-v-R for impulse responses. Of course, in both cases, these are mostly for reverb, as that's quite popular...

If you want to know more about convolution and finite impulse response filtering, try googling. There's a coder's tutorial on lycos (with lots of cookies) that goes some way to explaining technically what happens. As I understand it, you capture the way something sounds and then apply that to something else...

Waveguide

sfz can use the sample provided as a waveguide, using waveguide ("on" or "off", default is off). Quite what it's guiding isn't clear but the samples provided sound quite nice. http://www.rgcaudio.com/sfzsamples/waveguide.rar

You may get the impression I haven't a clue how this works or much grip on what it is. You'd be right. All I can do is direct you to try googling, or try this Harmony Central article.

New/Beta/Unofficial Opcodes

Some new opcodes have been added to sfz format since July 2004 (when the spec stabilised). These are not yet part of the spec.

pitch_keycenter=sample
A region with this coded uses the root note value from the sample, if present - otherwise 0.
sample_fadeout
The (float) value represents the number of seconds before the end of sample playback that the player should begin a realtime fadeout. The fadeout end coincides with playback end. See also Amplifier.
delay_beats
The (float) value represents the number of beats to delay the trigger point for the layer (assuming there's some way of detecting a host tempo). See When to play.
xxx_cc#
In addition to the MIDI standard controller numbers, the following are also defined:

For control by

Use CC number

pitch bend

128

channel aftertouch

129

polyphonic aftertouch

130

Note On velocity

131

Note Off velocity

132

keyboard (note number)

133

keyboard (note gate)

134

unipolar random (0 to 1)

135

bipolar random (-1 to 1)

136

These can be used wherever a xxx_cc# opcode is mentioned. In addition, many of the "uncontrollable" parameters can also take this form (pan for example). I'd suggest just trying it out.

The value given for the opcode controls the "depth" of the adjustment.

For controllers with ranges 0 to 127, this is as explained above - the adjustment made is:
(depth times CC value / 127)

For pitch bend, the depth is multiplied by the current position is divided by 8192.

For note gate, the depth is multiplied by either zero (no key down) or 1 (any key down).

For the the random CCs, the depth is multiplied by a random number in the range stated.

IMPORTANT NOTE: This feature is not considered complete. The numbers above are subject to change. Don't do anything that would be difficult to change before these are finalised. René says: Just note that cc136 will also fill any document in your pc with the sfz rocks phrase. ;-)


Valid XHTML 1.1! Valid CSS!

© 2004, 2005 Peter L Jones. All rights reserved. Contact me if you want to republish.

If you find any problems or have any questions, please let me know: < peter !at! drealm !dot! info >

Last updated: 16 Apil 2014
Clarify use of "rt_decay" when calculating amplitude of a "trigger=release" layer.
3 June 2009: Link to my VelLeveler utility page; updated "official" documentation link
2 June 2009: Update with better explanation of how to map non-normalised samples
29 November 2007: Reference Simon Cann's book
4 July 2005Further explanation around amp_velcurve_nnn supplied and email address updated.
6 February 2005: Reviewed document following note from René asking for a round up of missing features. Many changes for clarity.
30 October 2004: Added the extended list of magic MIDI CC numbers, making them more clearly "unreliable". Fixed a number of typos.
11 October 2004: Added "volume" (at last!), "sample_fadeout" and "delay_beats" opcodes and "sample" value for pitch_keycenter. Added "magic" CC numbers.
18 July 2004: Added the "Undocumented" features section.
17 July 2004: Made the markup XHTML 1.1 and CSS 2.1 compliant.
17 July 2004: As finished as it's going to be until the outstanding questions get asked and answered.
17 July 2004: Nearly finished - outstanding questions, EQ, Sends and outputs only left.
11 July 2004: Uploaded