SFZero sound font player, now available as Juce module


#1

If your projects could use a Juce synth that can play SF2 and SFZ soundfonts, this might interest you.

I have taken the liberty to update Steve Folta's great SFZero player a little and convert it to a Juce module.  So it's now dead easy to use it from within your code.

The source code can be found here: https://github.com/altalogix/SFZero.  It's MIT/BSD-style licensed - as was the original.

And I wrote a little blog article about it as well : http://www.mucoder.net/blog/2016/03/24/sfzero.html

Have fun
Leo

(posted earlier at Audio Plugins board - but this is a better place)


#2

Cool stuff :)


#3

could you separate the juce module and the example, so that it can be easily included in a project as a git submodule?


#4

makes sense. Will look into it


#5

Thanks! This is very useful! I’ve looked in the original version and was discouraged to try and update it to latest once I saw it used a very old version of JUCE.

Few things I had to fix before running on latest (4.2.1) JUCE:

Probably this changed with the latest version, and now the common includes (SFZCommon.h) need to look like this:

#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_audio_formats/juce_audio_formats.h>
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_gui_basics/juce_gui_basics.h>

Every project pointed to a VST 3 SDK specific for your FS.

My SFZ instrument is based on .FLAC, so I had to change this in the example:

sfzero::SFZeroAudioProcessor::SFZeroAudioProcessor() : loadProgress(0.0), loadThread(this)
{
  formatManager.registerBasicFormats();
  // instead of:
  // formatManager.registerFormat(new WavAudioFormat(), false);
  // formatManager.registerFormat(new OggVorbisAudioFormat(), false);

  // ...
}

Cheers!


#6

good catch tsenkov, I’ve added your changes to the repo. Works with juce 4.1 here as well.

as to the VST SDK, that’s difficult to fix as this is a global Projucer setting. It’s always best to load and save the .jucer project file once in order to regen the build scripts with your own preferences

thanks
Leo


#7

hey Oli, I’ve now separated out the module into a submodule at

can you have a look if it works for you this way?


#9

ah, yes. Unfortunately the SFZero repo was already in use as the parent repo - so I had to pick another name.
Would it be helpful to rename SFZero.h to SFZeroModule.h instead?


#10

could do. I have called my juce modules juce_modulename to match what Jules does


#11

Hi Leo,

i would like to include your SFZero module as a sound source for my plugin, but i’m not getting too far with it.

can you (or somebody) please outline the basic steps to use this in inside an AudioProcessor?

edit: ahhh, don’t worry, i think i can see now. Read the blog post, has helped…will post again if i get stuck

edit2: woohoo! got it working! was way easier than i expected! thanks so much Leo!


#12

I think a better format is vendor_module name or just modulename - I see juce_ as a prefix for Juce internal modules.


#13

I’m getting a leak whenever I quit my project in sfzero::Sample. I’m using it like this:

SynthAudioSource::SynthAudioSource(MidiKeyboardState& state) : keyboardState(state)
{
    midiCollector.reset(44100);
    for( int i = 0; i < 16; ++i)
    {
        synth.addVoice( new sfzero::Voice() );
    }
    
    AudioFormatManager formatManager;
    formatManager.registerBasicFormats();
    
    auto sf2File = File::getSpecialLocation( File::SpecialLocationType::currentApplicationFile).getChildFile("Contents").getChildFile("Resources").getChildFile("TimGM6mb.sf2");
    auto* sound = new sfzero::SF2Sound( sf2File );
    sound->loadRegions();
    sound->loadSamples(&formatManager);
    sound->useSubsound(4); //E.Piano 1
    
    synth.clearSounds();
    synth.addSound( sound );
}

SynthAudioSource::~SynthAudioSource()
{
    synth.clearSounds();
    synth.clearVoices();
}

any ideas what is causing sfzero::Sample to leak?

*** Leaked objects detected: 8 instance(s) of class sfzero::Sample

#14

I’m going through the codebase, and see a lot of things like this:

class Sample
{
// snip
    virtual ~Sample();
private:
    juce::AudioSampleBuffer* buffer_;
};

sfzero::Sample::~Sample()
{
    delete buffer_;
}

that is pretty hard to look at in 2018. Is there any particular reason this module isn’t doing things like this:

private:
    juce::ScopedPointer<juce::AudioSampleBuffer> buffer_;

that handles all of the automatic deletion, and functions like this are immediately much simpler:

juce::AudioSampleBuffer *sfzero::Sample::detachBuffer()
{
    /*
    juce::AudioSampleBuffer *result = buffer_;
    buffer_ = nullptr;
    return result;
     */
    return buffer_.release();
}

#15

Looks like it could do with some updating to use smart pointers…


#16

Already done: https://github.com/matkatmusic/SFZeroModule/tree/JUCECleanup