Skip to content

SoundFont

SoundFontInstrument loads a SoundFont (.sf2) bank and plays instruments from it as real, polyphonic audio. You drive it with note/controller events — noteOn, noteOff, controlChange, pitchBend — from any source (the computer keyboard, a gamepad, a music chart, or a MIDI device), and it renders through the streaming audio sink. It is powered by TinySoundFont (MIT). Introduced by engine PLM-134 (ADR 0043).

The bank file is a normal loaded resource read through the mounted project (like audio and images) — banks are large, so games typically keep them out of source control and fetch them at runtime.

SoundFontInstrument.new(path, sampleRate, channels)

Section titled “SoundFontInstrument.new(path, sampleRate, channels)”

Loads a .sf2 bank from the mounted project and creates the instrument’s own streaming audio source.

Parameters:

  • path (String) — Path to the .sf2 bank relative to the mounted project (e.g. "soundfonts/piano.sf2").
  • sampleRate (Num) — Render sample rate in Hz (e.g. 48000).
  • channels (Num) — 1 for mono or 2 for stereo.

Returns: a SoundFontInstrument. Check loaded — it is false if the bank was missing or could not be parsed (the object is still safe to call; it just makes no sound).

import "engine" for SoundFontInstrument
_piano = SoundFontInstrument.new("soundfonts/piano.sf2", 48000, 2)
if (!_piano.loaded) System.print("bank not found")
_piano.setPreset(0)

Notes are standard MIDI note numbers (0127; 60 = middle C). Velocity is 0.01.0.

Starts a note on the current preset. Velocity 0 acts as a note-off. Polyphonic — call it repeatedly for a chord.

Releases a note. The note enters its release envelope (it is not instantly silent).

Releases every sounding note.

_piano.noteOn(60, 0.9) // middle C
_piano.noteOn(64, 0.9) // E — now a two-note chord
_piano.noteOff(60)

Selects the voiced preset (instrument) by bank-slot index, 0presetCount − 1.

Sends a MIDI continuous controller (both 0127). For example controller 64 is the sustain pedal (127 = down, 0 = up).

Sets pitch bend as a 14-bit value 016383; 8192 is centered.

Caps simultaneous voices (polyphony).

Master gain in decibels (0 = unity).

Returns: Bool — whether the bank loaded successfully.

Returns: Num — the number of presets (instruments) in the bank.

Returns: String — the name of a preset, or "" if out of range.

Returns: Num — how many voices are currently sounding.

The engine renders and queues the instrument’s audio automatically every frame — you don’t call anything to keep it flowing. Just trigger notes; the sound follows.

class Game {
init() {
_piano = SoundFontInstrument.new("soundfonts/piano.sf2", 48000, 2)
_piano.setPreset(0)
}
update(dt) {
if (Input.keyJustPressed("a")) _piano.noteOn(60, 0.9)
}
}
  • The note source is irrelevant. Any input can drive the instrument — a keyboard, a gamepad, a chart, or a MIDI device.
  • Route it through the mixer. An instrument is a normal sound source; add it to a mixer group with group.addInstrument(instrument) to control it alongside your other audio (volume, mute, solo).
  • Bank files are loaded resources. A .sf2 is read through the mounted project (PhysicsFS-sandboxed); keep large licensed banks out of git and load them at runtime, as the SoundFont Piano example does.
  • Rendering path. The instrument renders float PCM into the engine’s streaming audio sink; it needs no backing audio file.
  • Audio — the streaming sink the instrument renders into.
  • Input — one way to trigger notes (a computer-keyboard piano).
  • Example: SoundFont Piano — a playable keyboard piano.