SFZero sound font player converted to a Juce 4.1 module

March 24, 2016  -  Leo Olivers

A while ago I was looking for a way to use SF2/SFZ sound fonts with a Juce-based synth. A sound font, is a sample library format that was all the rage in the nineties - when Creative Labs’ Soundblaster AWE32 was the hottest sound card around for your Pentium 1 PC. Nowadays there is a modern, more open equivalent: SFZ, which was pioneered by rgc:audio and used by various vendors such as Cakewalk.

The bottom line is, there are lots of SF2 and SFZ sample libraries available, many of them free, and they’re an obvious choice as a sample format to support within a Juce-based synth.

Surely Juce does that already??

I had my hopes up that the incredible richness of the Juce library would turn up a nifty loader for .SF2 or .SFZ files, but alas : there’s only support for loading individual sample files, but nothing like a sample pack format loader.

In retrospect that’s not that surprising: SF2 and SFZ files not only contain samples but also lots of metadata for tweaking the samples (like loop boundaries, midi-note-to-sample mappings, envelope definitions, filter parameters etc). So calling this a sample loader is doing it injustice, you would also need a quite sophisticated sample player that understands all that metadata. You could of course build one, starting from the Juce built-in Synthesiser/SamplerVoice classes, but that’s not exactly a one-weekend project.

SFZero

Not wanting to reinvent the wheel, I checked the internet first, and found Steve Folta’s wonderful SFZero. Which also happened to be the only game in town when looking for something that a) supports Juce and b) has a permissive license.

sfzero plugin

But, (there is always a but) SFZero

  • isn’t really a standalone lib, it’s more of an open source sample player plugin
  • didn’t really seem to be actively maintained (last updated 3 years ago)
  • did not compile against the latest Juce 4.x release, and there were lots of warnings when compiling against an older Juce 3.x

SFZero, the Module

All of that can be fixed of course. So I took the liberty to fork it to an improved version which

  • has been converted to a Juce module, so you can easily consume it from your own projects (you still get the sample player plugin, but it now includes that module)
  • compiles against Juce 4.1
  • conveniently sits within its own sfzero:: namespace
  • has a tidied-up code base, so it now builds with as few warnings as possible on all platforms and on both 32/64 bit architectures. I also simplified logging, added support for synchronous sample loading, and fixed a few bugs.

Using SFZero from your code

If you are familiar with how the juce::Synthesiser class works (and its close associates, juce::SynthesiserVoice and juce::SynthesiserSound), then you’ll be right at home with SFZero.

SFZero comes its own sfzero::Synth, sfzero::Voice and sfzero::Sound / sfzero::SF2Sound classes. These are all specializations of their corresponding Juce base classes. Using it is a snap:

sfzero synth setup

You can also load sounds on a separate thread. For an example, have a look at the SFZeroAudioProcessor::loadSound() function in the SFZero player plugin that’s included in the source code. You can use this plugin as a basis for your own player. It basically does what any Juce-based plugin does: define an AudioProcessor-derived class, and override the processNextBlock() function. Within that function you then let your SFZero synth render its audio into the provided audio buffer.

Is there anything missing ?

While absolutely wonderful, SFZero is not perfect. The SF2 and SFZ standards define a lot of so called ‘opcodes’ or parameters, and SFZero does not support all of them currently. It does support the main ones though, and it will warn you if your soundfont has opcodes that it cannot deal with. But hey, that means there are opportunities for someone looking for a new challenge (pull requests welcome)

Where can I get it?

You can find it on github at github.com/altalogix/SFZero