The SFZ File Format: Create Your Own Virtual Instruments
By Anderton |
If You’re not Yet Conversant with Programming SFZ Files, It’s Time to Learn
by Craig Anderton
The SFZ file format maps samples to virtual instruments, and is used primarily in virtual instruments made by Cakewalk, including DropZone, RXP, SFZ, Session Drummer 2, and LE versions of Dimension and Rapture. However, it's an open standard, and others (such as Garritan) are using it as well; furthermore, there's a free SFZ player VST instrument so you can create your own virtual instrument by creating an SFZ file, then loading it into the player. Overall, this is a protocol who's time has come, and we'll walk you through the basics.
THE SFZ FILE FORMAT
The SFZ file format is not unlike the concept of SoundFonts, where you can load a ready-to-go multisampled sound - not just the samples - as one file. Unlike SoundFonts, which are monolithic files, the SFZ file format has two components: A group of samples, and a text file that "points" to these samples and defines what to do with them. The text file describes, for example, a sample's root key and key range. But it can also define the velocity range over which the sample should play, filtering and envelope characteristics, whether notes should play based on particular controller values, looping, level, pan, effects, and many, many more parameters.
However, note that not all SFZ-compatible instruments respond to all these commands; if you try to load an SFZ file with commands that an instrument doesn't recognize (possibly due to an SFZ version 2 definition file being loaded into an SFZ version 1-compatible instrument), the program will generate an error log in the form of a text message. Fortunately, nothing crashes, and the worst that can happen is that the file won't load until you eliminate (or fix, in the case of a typo or syntax error) the problematic command.
It's worth mentioning that the SFZ spec is license-free, even for commercial applications. For example, if you want to sell a set of SFZ-compatible multisamples for use in the Cakewalk synths, you needn't pay any kind of fee or royalty.
WHY BOTHER LEARNING ABOUT SFZ FILES?
There are three main reasons:
- If you like to create your own sounds, you can create far more sophisticated ones for SFZ-compatible instruments if you know how the SFZ format works. And, the files you create will load into other SFZ-aware instruments (particularly if you limit yourself to using commands from the version 1.0 SFZ spec).
- By editing SFZ files, you can overcome some of the limitations in the LE versions of Rapture and Dimension included in Sonar. It's been pointed out that you can't adjust tuning in the LE versions...and you can't, which can be a real problem if you recorded a piano track where the piano was in tune with itself, but not tuned to concert pitch - and you want to add an overdub. However, you can edit the tuning of the SFZ file itself loaded into the instrument, and compensate for tuning that way.
- SFZ files provide a way for cross-host collaboration. The SFZ Player (Fig. 1) included in Sonar, a VST plug-in that works in any VST-compatible host, is available as a free download.
Fig. 1: The SFZ Player is a free download that works in any VST-compatible host, not just Sonar.
As to why this is important, suppose you're using Sonar, a friend is using Ableton Live, and you want to collaborate on a part based on some samples you've grabbed. String those samples together into an SFZ file, have your friend download the player, send the SFZ file to your friend, and you can swap parts back and forth. You can even use really big samples, because the SFZ player supports compressed Ogg Vorbis files. So, you can create a compressed, "draft" version of the SFZ file, then substitute a full version with WAV files when it's mixdown time.
CREATING YOUR FIRST SFZ FILE
Creating an SFZ file is not unlike writing code, but don't panic: It's easier than writing music! Despite the many commands, you don't need to learn all of them, and the syntax is pretty straightforward. Although you can "reverse-engineer" existing SFZ files to figure out the syntax, it's helpful to have a list of the available commands - you can find one at http://www.cakewalk.com/DevXchange/sfz.asp (Fig. 2), or check out Appendix A in the book "Cakewalk Synthesizers" by Simon Cann (published by Thomson Course Technology)
Fig. 2: All the opcodes (commands) for the 1.0 version of the SFZ spec are listed and described on Cakewalk's web site.
As an example of how the SFZ protocol can dress up a sample, suppose you've sampled a guitar power chord in D and extracted a wavetable from it - a short segment, with loop points added in an audio editor (we'll call the sample GuitWavetable\_D1.WAV). It won't sound like much by itself, but let's create an SFZ file from it, and load it into SFZ Player.
Arguably the two most crucial SFZ concepts are "region" and "group." Region defines a particular waveform's characteristics, while Group defines the characteristics of a group of regions. For example, a typical Region command would be to define a sample's key range, while a typical Group command might add an attack time to all samples in an SFZ multisample. Another important element is the Comment. You can add comments to the definition file simply by adding a couple slashes in front of the comment, on the same line; the slashes tell SFZ to ignore the rest of what's on the line.
Here's a suggested procedure for getting started with SFZ files.
1. Create a folder for the samples you plan to use. In this case, I called mine "GuitarWavetables."
2. Drag the sample(s) you want to use into the folder you created. In this example, I used only one sample to avoid complications.
3. Open up a text editor, like Notepad (the simpler, the better-you don't need formatting and other features that add extraneous characters to the underlying text file). If you do use a word processor like Word, make sure you save the file as plain MS-DOS text.
4. Add some comments (putting // before text turns it into a comment) to identify the SFZ file, like so...
// SFZ Definition File
// Simple Guitar Wavetable File
5. Let's turn this wavetable into a region that spans the full range of the keyboard. To do this we need to add a line that specifies the root key, the key range, and tells the file where to find the sample. Here's the syntax:
<region> pitch\_keycenter=D1 lokey=C0 hikey=C8 sample=GuitWavetable\_D1.WAV
That's all pretty obvious: pitch\_keycenter is the root key, lokey is the lowest key the sample should cover, hikey is the highest key the sample should cover, and sample defines the sample's name. As the definition file and sample are in the same folder, there's no need to specify the folder that holds the sample. If the definition file is "outside" of the folder, you'd change the sample= line to include the folder, like so:
6. Save this text file under the file name you want to use (e.g., "GuitarPowerChordWave.sfz") in the GuitarWavetables folder. You could actually save it anywhere, but this way if you move the folder, the text definition file and samples move together. (Note that you can right click on an SFZ file and "open with" Notepad - you don't have to change the suffix to TXT.)
7. Open up an SFZ-compatible instrument, like Dimension LE. Click in the Load Multisample window that says "Empty," then navigate to the desired SFZ file (Fig. 3). Double-click on it, and now you should hear it when you play Dimension. If you don't, there might be a typo in your text file; check any error message for clues as to what's wrong.
Fig. 3: Click in the Load Multisample field in Dimension or Rapture, and a Load Multisample browser will appear; navigate to what you want to load. The Garritan Pocket Orchestra samples for Dimension LE are a rich source of SFZ files.
TAKING IT FURTHER
Okay, we can play back a waveform...big deal. But let's make it more interesting by loading two versions of the same waveform, then detuning them slightly. This involves adding a tune= description; we'll tune one down -5 cents, and the other up 5 cents. Here's how the file looks now:
<region> pitch\_keycenter=D1 lokey=C0 hikey=C8 tune=-5 sample=GuitWavetable\_D1.WAV
<region> pitch\_keycenter=D1 lokey=C0 hikey=C8 tune=5 sample=GuitWavetable\_D1.WAV
Now let's pan one waveform toward the right, and the other toward the left. This involves adding a descriptor of *pan= *where the value must be between -100 and 100.
Next up, we'll add one more version of the waveform in the center of the stereo image, but dropped down an octave to give a big bass sound. We basically add a line like the ones above, but omit tune= and add a transpose=-12 command.
Loading the SFZ file now loads all three waveforms, panned as desired, with the middle waveform dropped down an octave. But it sounds a little buzzy for a bass, so let's add some filtering, with a decay envelope. This is a good time for the <group> function, as we can apply the same filtering to all three oscillators with just one line. And here is that line, which should be placed at the top of the file:
<group> fil\_type=lpf\_2p cutoff=300 ampeg\_decay=5 ampeg\_sustain=0 fileg\_decay=.5 fileg\_sustain=0 fileg\_depth=3600
Here's what each function means:
fil\_type=lpf\_2p This indicates that the filter type is a lowpass filter with 2 poles.
cutoff=300 Filter cutoff in Hertz
ampeg\_decay=5 The amplitude envelope generator has a decay of 5 seconds
ampeg\_sustain=0 The amplitude envelope generator has a sustain of 0 percent.
fileg\_decay=.5 The filter envelope generator has a decay of 0.5 seconds.
fileg\_sustain=0 The filter envelope generator has a sustain of 0 percent.
fileg\_depth=3600 The filter envelope generator depth is 3600 cents (3 octaves).
As you work with SFZ files, you'll find they're pretty tolerant - for example, the sample names can have spaces and include any special characters other than =, and you can insert blank lines between lines in the SFZ definition text file. But one inviolable rule is that there can't be a space on either side of the = sign.
Rapture LE and Dimension LE are useful additions to Sonar, but as playback-oriented instruments, they have limitations compared to the full versions. For example, with Dimension LE, you can edit two stages of DSP, a filter, and some global FX-nothing else, like tuning, transpose, envelope attack, and other important parameters. However, if the sound you want to load into either of these LE versions is based on an SFZ file, you can modify it well beyond what you can do with the instruments themselves. (Note that these instruments often load simple WAV or other file types instead of the more complex SFZ types; in this case, editing becomes more difficult because you have to first turn the WAV file into an SFZ file, and if you're going to put that much effort into programming, you might want to upgrade to the full versions that have increased editability.)
Let's look at a Dimension patch, Hammond Jazz 3. This loads an SFZ file called Hammond jazz.sfz, so it's ripe for editing. We'll take that Hammond sound and turn it into a pipe organ by creating two additional layers, one an octave above the original sound, and one an octave lower. We'll pan the octave higher and main layers right and left respectively, with the lower octave panned in the middle. Then we'll tweak attack and release times, as well as add some EQ. Here's how.
1. To find the SFZ file, go to C:\Program Files\Cakewalk\Dimension LE\Multisamples\Organs and open Hammond Jazz.sfz in Notepad. Here's what it looks like:
<region> sample=Hammond Jazz\HBj1slC\_2H-S.wav key=c3 hikey=f3
<region> sample=Hammond Jazz\HBj1slC\_3H-S.wav key=c4 hikey=f4
<region> sample=Hammond Jazz\HBj1slC\_4H-S.wav key=c5 hikey=f5
<region> sample=Hammond Jazz\HBj1slD\_5H-S.wav key=d6 hikey=f6
<region> sample=Hammond Jazz\HBj1slC\_6H-S.wav key=c7 hikey=f7
<region> sample=Hammond Jazz\HBj1slF#1H-S.wav key=f#2 hikey=b2 lokey=c1
<region> sample=Hammond Jazz\HBj1slF#2H-S.wav key=f#3 hikey=b3
<region> sample=Hammond Jazz\HBj1slF#3H-S.wav key=f#4 hikey=b4
<region> sample=Hammond Jazz\HBj1slF#4H-S.wav key=f#5 hikey=c#6
<region> sample=Hammond Jazz\HBj1slF#5H-S.wav key=f#6 hikey=b6
2. This shows that the SFZ definition file basically points to 10 samples, with root keys at various octaves of C or F#, and spreads them across the keyboard as a traditional multisample. Note that it doesn't use the pitch\_center= statement, for two reasons: First, Dimension LE doesn't recognize it, and second, because the key= statement sets the root key, low key, and high key to the same value. You can add modifiers to this, like lokey= and hikey= statements, as needed.
3. Before this block of <region> statements, add a <group> statement as follows to modify all of these regions:
<group> ampeg\_attack=0.2 ampeg\_release=2 pan=-100 eq1\_freq=4000 eq1\_bw=2 eq1\_gain=20
These parameters add an amplifier envelope generator attack of 0.2 seconds, amplifier envelope generator release time of 2 seconds, pan full left, and one stage of EQ (with a frequency of 4kHz, bandwidth of two octaves, and 20dB gain).
4. Now we'll add another region an octave lower, and put a similar <group> statement before it. We'll simply use one of the existing samples and to minimize memory consumption, as this sample plays more of a supportive role, we'll just stretch it across the full keyboard range.
<group> ampeg\_attack=0.2 ampeg\_release=1 transpose=-12 eq1\_freq=2000 eq1\_bw=4 eq1\_gain=20
<region> sample=Hammond Jazz\HBj1slC\_4H-S.wav key=c5 lokey=c0 hikey=c8
The group statement is very similar to the previous one, except that the sample has been transposed down 12 semitones, the pan statement is omitted so the sample pans to center, and the EQ's center frequency is 2kHz instead of 4kHz. The sample's root key is C5, and stretched down to C0 and up to C8.
5. Next, we'll add the final new region, which is an octave higher. Again, we'll put a <group> statement in front of it.
<group> ampeg\_attack=0.2 ampeg\_release=1 transpose=12 pan=100
<region> sample=Hammond Jazz\HBj1slC\_4H-S.wav key=c5 lokey=c0 hikey=c8
The group statement adds the familiar attack and release, but transposes up 12 semitones and pans full right. The region statement takes the same sample used for the octave lower sound and stretches it across the full keyboard.
I should add that although we've made a lot of changes to the SFZ file, it's still being processed by Dimension LE's Hammond Jazz 3 patch. As a result, if you take this SFZ file and load it into SFZ player, it won't sound the same because it won't be using the various Dimension parameters that are part of the Hammond Jazz 3 patch.
ARE WE THERE YET?
Explaining all this on paper may make the process of creating SFZ files seem complex, but really, it isn't as long as you have the list of SFZ opcodes in front of you. After a while, the whole process becomes second nature.
For example, I found an SFZ bass patch that produced a cool, sort of clav-like sound when I transposed it up a couple octaves-but the attack sounded cartoonlike when transposed up that high. So, I just used the offset= command to start playback of the samples past the attack. And while I was at it, I added a very short attack time to cover up the click caused by starting partway through the sample, and a decay time to give a more percussive envelope. The editing took a couple of minutes at most; I saved the SFZ file so I could use this particular multisample again.
Sure, creating SFZ files might not replace your favorite leisure time activity-but it's a powerful protocol that's pretty easy to use. Modify some files to do you bidding, and you'll be hooked.
Craig Anderton is Editor Emeritus of Harmony Central. He has played on, mixed, or produced over 20 major label releases (as well as mastered over a hundred tracks for various musicians), and written over a thousand articles for magazines like Guitar Player, Keyboard, Sound on Sound (UK), and Sound + Recording (Germany). He has also lectured on technology and the arts in 38 states, 10 countries, and three languages.