Including SoundFonts for Cross Platform Support


#1

Currently, in my JUCE app I load SoundFonts from my Xcode resource folder.

void MainComponent::setupSoundfont()
    {
        String soundfontFilePath (File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile).getFullPathName());
        soundfontFilePath += "/Contents/Resources/Electric Piano.sf2";
        const File soundfontFile (soundfontFilePath);
        audioSource.loadSoundfont (soundfontFile);
    }

I need this app to run on windows machines also, however.

What would be the best way to go about this? Can I load the .sf2 file if I include it as binary data somehow?


#2

You can use JUCE’s BinaryResource feature. Add the file in the Projucer, mark it as a Binary Resource, and save the project. You will then be able to access it in binary form from your project via BinaryData::Electric_Piano_sf2 and BinaryData::Electric_Piano_sf2_size.


#3

How would I then go about loading that into a FILE object? This is my attempt… MemoryMappedFile looks like this could be useful?

MemoryBlock mem (BinaryData::Electric_Piano_sf2,
                   BinaryData::Electric_Piano_sf2Size);
const File soundfontFile;
soundfontFile.loadFileAsData (mem);
audioSource.loadSoundfont (soundfontFile);

#4

AFAIK, you can’t get it into a juce::File object directly, as juce::File represents a file on the hard drive.

What’s the type of audioSource? The class should expose means of loading a soundfont other than from a file, e.g. from a MemoryInputStream or from the binary data directly.

If you need a juce::MemoryInputStream:

juce::MemoryInputStream mis(BinaryData::Electric_Piano_sf2,
                            BinaryData::Electric_Piano_sf2Size, false);

#5

BinaryResource is good for small amounts of data.
but if you’re going to have gigabytes of data it could be very frustrating resulting bugfix release to actually contain the binary data again and linking to take longer (I also remember there’s a limit due to VS linker).

You can use your sf2 files but…

  • as a user (and ironically a mac one :slight_smile: ), it would be easier for everyone to allow me to set where the “soundbank” is located. Apple soldered my SSD :frowning: and I’d might like to put it elsewhere. (and an end-user won’t know much about symlinks…) so…
    a preference file for your product would be very useful.
    Check juce::PropertiesFile.

  • File locations, juce::File would also provide you some common paths commonApplicationDataDirectory.

  • in addition, cross-platform coding with JUCE is indeed minimal branching. but you’d like to use platform specific macros. (in juce that is - #JUCE_MAC and #JUCE_WINDOWS iirc)

If you’ve already release the product you can still limit the new locations to be used on Windows.


#6

That’s excellent advice. If the SoundFonts are large and not static, and you want to allow the user to load more of them, you should implement a file choosing mechanism. In that case, you could ship an installer, which installs the sound fonts to a system directory (like ~Library/Audio/...), and read soundfonts from that folder.


#7

Yep! Seems like that’s the smartest option.

I’ll leave the Xcode resources for the MAC version, and create a new user-specified path for the files on windows.

Thanks all!


#8

One thing to keep in mind is that Windows has a limitation on EXE file sizes, not sure if it is your case. Ignore me if it’s not. :wink:

I created my own way to embebed files into EXE files on Windows for using with my installer. Is not great, but works on all systems so far.

Cheers, WilliamK