What is sfMidi?
sfMidi is a static library for playing MIDI files with SoundFont 2 in SFML.
sfMidi uses FluidSynth (http://sourceforge.net/apps/trac/fluidsynth/ (http://sourceforge.net/apps/trac/fluidsynth/)) to load SoundFont 2 and MIDI files.
GitHub repository:
https://github.com/eXpl0it3r/sfMidi (https://github.com/eXpl0it3r/sfMidi)
Hand over to new maintainer:
After a long period of inactivity, I have decided to hand over this project to eXpl0it3r (https://en.sfml-dev.org/forums/index.php?action=profile;u=3414).
Please checkout the GitHub repository for the latest updates on this project.
Note:
FluidSynth does not support seeking by itself, therefore, in order to seek forward, sfMidi reads and ignores the audio data from FluidSynth until it reaches the desired offset.
However, in order to seek backwards, sfMidi has to reload the MIDI data, and seek forward from the beginning again, hence, seeking backwards will be slower than seeking forward.
Naturally, stopping is considered seeking to the beginning and playing it again, which means the MIDI data has to be reloaded again if we want to stop the MIDI. Thankfully, reloading the MIDI data doesn't take much time.
Also, for looping, I've tried using both the SFML and FluidSynth's loop feature, but unfortunately they did not work at all, so I had to implement my own loop function, which again, requires reloading the MIDI data.
Edit:
I've added a feature to preload MIDI data into audio samples in version 1.0.1, this means you can load the entire MIDI data into memory as audio samples, and this will result in faster and more efficient playback (no more problems with seeking).
Preloading takes quite some time to load, so be careful in choosing whether to preload or not.
Of course, preloading the MIDI data into audio sample means you get to unload the sound font, so you get to save quite some memory, unless your song is long enough to be larger than the sound font.
Preloading takes about 10MB of memory per minute.
I think he was referring to this kind of solution:
class MidiBackend
{
// whatever is required as virtual functions
};
class FluidSynthBackend : public MidiBackend
{
// implement virtual functions
};
class PortMidiBackend : public MidiBackend
{
// implement virtual functions
};
class sfMidi
{
public:
void loadFromFile(std::string filename)
{
delete m_backend;
m_backend = new PortMidiBackend(filename);
...
}
void loadFromFile(std::string filename, std::string soundfont)
{
delete m_backend;
m_backend = new FluidSynthBackend(filename, soundfont);
...
}
private:
MidiBackend* m_backend;
};