Skip to main content

Custom SoundFonts

The bundled Sonivox SoundFont covers General MIDI but is deliberately small. When the score needs a Steinway rather than a GM piano, a metal amp emulation rather than a clean guitar, or a rock drum kit rather than the stock kick and snare, swap in a purpose-built .sf2 file. The synth pipeline stays identical โ€” only the sample bank changes.

The score below is the opening bars of Beethoven's Ode to Joy voiced as a chord-melody โ€” long, sustained notes give the sample bank room to speak. Toggle the SoundFont to hear the same MIDI events re-rendered through a different bank.

00:00 / 00:00
bundled Sonivox active

The two options give an audible A/B: the bundled Sonivox is a compact General-MIDI bank tuned for small footprint; GeneralUser GS by S. Christian Collins is a refined GM/GS bank (about 9 MB as compressed SF3) with Steinway-lineage piano samples and richer guitar/drum presets. Toggle to hear the same MIDI events re-rendered through a much fuller-bodied bank. GeneralUser GS is redistributed here under its author's permissive license (commercial and modification allowed).

Two ways to load oneโ€‹

  • api.loadSoundFont(data) โ€” pass a Uint8Array or ArrayBuffer of SoundFont bytes and alphaTab wires them into the synth. Works on every runtime.
  • api.loadSoundFont(url) โ€” on Web only, pass a URL string and alphaTab downloads the file for you.

Both forms replace whatever is currently loaded โ€” the second parameter, append, defaults to false. When it fires, api.soundFontLoaded signals that the synth is ready. Trigger api.resetSoundFonts() to release all presets and free the memory before loading a fresh one.

Show it in codeโ€‹

import * as alphaTab from '@coderline/alphatab';

const container = getAlphaTabContainer();
const api = new alphaTab.AlphaTabApi(container, {
core: { file: '/scores/song.gp' },
player: {
playerMode: alphaTab.PlayerMode.EnabledSynthesizer,
},
});

api.soundFontLoaded.on(() => {
console.log('Ready for playback.');
});

// Swap in a bytes-based SoundFont.
const bytes = await readScoreFile('/assets/fluidr3-guitars.sf2');
api.loadSoundFont(bytes);

// Later, drop everything and load a different one.
api.resetSoundFonts();
const drums = await readScoreFile('/assets/rock-drums.sf2');
api.loadSoundFont(drums);

getAlphaTabContainer() is a placeholder for the platform-specific step of obtaining the render target โ€” a <div> on Web, an AlphaTab control on .NET, or an AlphaTabView on Android.

readScoreFile() is a placeholder for the platform-specific step of producing a Uint8Array โ€” fs.promises.readFile on Node.js, System.IO.File.ReadAllBytes on .NET, ContentResolver.openInputStream on Android, or fetch(...).then(r => r.arrayBuffer()) in the browser.

Picking a SoundFontโ€‹

  • SoundFonts are a public format โ€” FluidR3, Timbres of Heaven, and many commercial packs work as-is.
  • Larger files mean better samples but longer downloads on Web. Trim unused presets with Polyphone before shipping.
  • If your score uses only guitars and drums, a 5 MB targeted SoundFont beats a 200 MB general-purpose one on both download time and RAM footprint.

Where to look nextโ€‹