A pure Go SoundFont2 (.sf2) synthesizer library.
- Full SF2 file parsing (RIFF chunks, pdta, sdta)
- ADSR volume envelope (Delay, Attack, Hold, Decay, Sustain, Release)
- Modulation envelope for filter and pitch
- Dual LFO (ModLFO and VibLFO) for vibrato and tremolo
- Lowpass filter with resonance
- Velocity and key tracking
- Pitch bend support
- 16 MIDI channels
- Sample looping
- Global zone inheritance
go get github.com/danielgatis/go-soundfontpackage main
import (
"log"
"github.com/danielgatis/go-soundfont/pkg/soundfont"
)
func main() {
// Load a SoundFont
sf, err := soundfont.New("path/to/soundfont.sf2")
if err != nil {
log.Fatal(err)
}
// Configure output
sf.SetOutput(soundfont.OutputStereo, 44100, 0)
// Set a preset on channel 0
presetIdx := sf.GetPresetIndex(0, 0) // Bank 0, Program 0
sf.ChannelSetPreset(0, presetIdx)
// Play a note
sf.NoteOn(0, 60, 0.8) // Channel 0, Middle C, velocity 0.8
// Render audio
buffer := make([]float32, 1024*2) // Stereo buffer
sf.Render(buffer, 1024, false)
// Stop the note
sf.NoteOff(0, 60)
}// Load from file
sf, err := soundfont.New("soundfont.sf2")
// Load from memory
sf, err := soundfont.NewFromMemory(data)
// Load from io.ReadSeeker
sf, err := soundfont.Load(reader)// Set output mode and sample rate
sf.SetOutput(soundfont.OutputStereo, 44100, gainDB)// Play a note (channel 0-15, key 0-127, velocity 0.0-1.0)
sf.NoteOn(channel, key, velocity)
// Release a note
sf.NoteOff(channel, key)
// Release all notes
sf.AllNotesOff()
// Release all notes on a channel
sf.ChannelAllNotesOff(channel)// Set preset (instrument)
sf.ChannelSetPreset(channel, presetIndex)
// Set volume (0.0 - 1.0)
sf.ChannelSetVolume(channel, volume)
// Set pan (0.0 = left, 0.5 = center, 1.0 = right)
sf.ChannelSetPan(channel, pan)
// Set pitch bend (-1.0 to 1.0)
sf.ChannelSetPitchBend(channel, bend)
// Set pitch bend range in semitones (default: 2)
sf.ChannelSetPitchRange(channel, semitones)// Get number of presets
count := sf.GetPresetCount()
// Get preset name
name := sf.GetPresetName(index)
// Find preset by bank and program number
index := sf.GetPresetIndex(bank, program)// Render audio samples
// output: stereo interleaved float32 buffer
// numSamples: number of sample frames (buffer size / 2)
// mix: if true, add to existing buffer content
sf.Render(output, numSamples, mix)See the examples directory for complete examples:
- basic - Simple note playback to WAV file
If you find this project useful, consider buying me a coffee!
MIT License - see LICENSE file.
Daniel Gatis