A powerful SF2/DLS/MIDI JavaScript library. It works with any modern JS environment that supports WebAssembly.
TIP: Looking for an easy-to-use WebAudioAPI browser wrapper? Try spessasynth_lib!
npm install --save spessasynth_core
Note: This is the new heart of the SpessaSynth library, after the repository has been split.
Project index
- spessasynth_core (you are here) - SF2/DLS/MIDI library
- spessasynth_lib - spessasynth_core wrapper optimized for browsers and WebAudioAPI
- SpessaSynth - online/local web player/editor application
- Modular design: Easy integration into other projects (load what you need)
- Detailed documentation: With examples!
- Flexible: It's not just a MIDI player!
- Easy to Use: Basic setup is just two lines of code!
- No dependencies: Batteries included!
- Suitable for both real-time and offline synthesis
-
Excellent SoundFont support:
- Full Generator Support
- Full Modulator Support: First (to my knowledge) JavaScript SoundFont synth with that feature!
- GeneralUserGS Compatible: See more here!
- SoundFont3 Support: Play compressed SoundFonts!
- Experimental SF2Pack Support: Play soundfonts compressed with BASSMIDI! (Note: only works with vorbis compression)
- Can load very large SoundFonts: up to 4GB! Note: Only Firefox handles this well; Chromium has a hard-coded memory limit
-
Great DLS Support:
- DLS Level 1 Support
- DLS Level 2 Support
- Mobile DLS Support
- Correct articulator support: Converts articulators to both modulators and generators!
- Tested and working with gm.dls!
- Correct volume: Properly translated to SoundFont volume!
- A-Law encoding support
- Both unsigned 8-bit and signed 16-bit sample support (24-bit theoretically supported as well!)
- Detects special articulator combinations: Such as vibratoLfoToPitch
- Soundfont manager: Stack multiple soundfonts!
- Unlimited channel count: Your CPU is the limit!
-
Excellent MIDI Standards Support:
- MIDI Controller Support: Default supported controllers here
- Portamento Support: Glide the notes!
- Sound Controllers: Real-time filter and envelope control!
- MIDI Tuning Standard Support: more info here
- Full RPN and limited NRPN support
- AWE32 NRPN Compatibility Layer
- Supports some Roland GS and Yamaha XG system exclusives
- Supports MIDI formats 0, 1, and 2: note: format 2 support is experimental as it's very, very rare.
- Multi-Port MIDI support: More than 16 channels!
- Smart preloading: Only preloads the samples used in the MIDI file for smooth playback (down to key and velocity!)
- Lyrics support: Add karaoke to your program!
- Raw lyrics available: Decode in any encoding! (Kanji? No problem!)
- Runs in Audio Thread as well: Never blocks the main thread
- Loop points support: Ensures seamless loops
- Smart name detection: Handles incorrectly formatted and non-standard track names
- Raw name available: Decode in any encoding! (Kanji? No problem!)
- Port detection during load time: Manage ports and channels easily!
- Used channels on track: Quickly determine which channels are used
- Key range detection: Detect the key range of the MIDI
- Easy MIDI editing: Use helper functions to modify the song to your needs!
- Loop detection: Automatically detects loops in MIDIs (e.g., from Touhou Project)
- First note detection: Skip unnecessary silence at the start by jumping to the first note!
- Lyrics support: Both regular MIDI and .kar files!
- Write MIDI files from scratch
- Easy saving: Save with just one function!
Read and write RMID files with embedded SF2 soundfonts
- Level 4 compliance: Reads and writes everything!
- Compression and trimming support: Reduce a MIDI file with a 1GB soundfont to as small as 5MB!
- DLS Version support: The original legacy format with bank offset detection!
- Automatic bank shifting and validation: Every soundfont just works!
- Metadata support: Add title, artist, album name and cover and more! And of course, read them too! (In any encoding!)
- Compatible with Falcosoft Midi Player 6!
- Easy saving: As simple as saving a MIDI file!
- Easy info access: Just an object of strings!
- Smart trimming: Trim the SoundFont to only include samples used in the MIDI (down to key and velocity!)
- sf3 conversion: Compress SoundFont2 files to SoundFont3 with variable quality!
- Easy saving: Also just one function!
- Same features as SoundFont2 but with now with Ogg Vorbis compression!
- Variable compression quality: You choose between file size and quality!
- Compression preserving: Avoid decompressing and recompressing uncompressed samples for minimal quality loss!
- Read DLS (DownLoadable Sounds) files as SF2 files!
- Works like a normal soundfont: Saving it as sf2 is still just one function!
- Converts articulators to both modulators and generators!
- Works with both unsigned 8-bit samples and signed 16-bit samples!
- A-Law encoding support
- Covers special generator cases: such as modLfoToPitch!
- Correct volume: looking at you, Viena and gm.sf2!
- Support built right into the synthesizer!
- Convert SF2 to DLS: with limitations
- Save the MIDI file as WAV audio!
- Metadata support: Embed metadata such as title, artist, album and more!
- Cue points: Write MIDI loop points as cue points!
- Loop multiple times: Render two (or more) loops into the file for seamless transitions!
- That's right, saving as WAV is also just one function!
- Synth's performance may be questionable sometimes
- SF2 to DLS Conversion limits
- Improve the performance of the engine
- Potentially port the system to Emscripten
- FluidSynth - for the source code that helped implement functionality and fixes
- Polyphone - for the soundfont testing and editing tool
- Meltysynth - for the initial low-pass filter implementation
- RecordingBlogs - for detailed explanations on MIDI messages
- stbvorbis.js - for the Vorbis decoder
- fflate - for the MIT DEFLATE implementation
- foo_midi - for useful resources on XMF file format
- Falcosoft - for help with the RMIDI format
- Christian Collins - for various bug reports regarding the synthesizer
- And You! - for checking out this project. I hope you like it :)
If you like this project, consider giving it a star. It really helps out!
import * as fs from "node:fs";
import { MIDI, SpessaSynthProcessor, SpessaSynthSequencer, audioToWav, loadSoundFont } from "spessasynth_core";
// process arguments
const args = process.argv.slice(2);
if (args.length !== 3)
{
console.log("Usage: node index.js <soundfont path> <midi path> <wav output path>");
process.exit();
}
const sf = fs.readFileSync(args[0]);
const mid = fs.readFileSync(args[1]);
const midi = new MIDI(mid);
const sampleRate = 44100;
const sampleCount = 44100 * (midi.duration + 2);
const synth = new SpessaSynthProcessor(sampleRate, {
enableEventSystem: false,
effectsEnabled: false
});
synth.soundfontManager.reloadManager(loadSoundFont(sf));
await synth.processorInitialized;
const seq = new SpessaSynthSequencer(synth);
seq.loadNewSongList([midi]);
seq.loop = false;
const outLeft = new Float32Array(sampleCount);
const outRight = new Float32Array(sampleCount);
const start = performance.now();
let filledSamples = 0;
// note: buffer size is recommended to be very small, as this is the interval between modulator updates and LFO updates
const bufSize = 128;
let i = 0;
while (filledSamples + bufSize < sampleCount)
{
const bufLeft = new Float32Array(bufSize);
const bufRight = new Float32Array(bufSize);
// process sequencer
seq.processTick();
const arr = [bufLeft, bufRight];
// render
synth.renderAudio(arr, arr, arr);
// write out
outLeft.set(bufLeft, filledSamples);
outRight.set(bufRight, filledSamples);
filledSamples += bufSize;
i++;
// log progress
if (i % 100 === 0)
{
console.log("Rendered", seq.currentTime, "/", midi.duration);
}
}
console.log("Rendered in", Math.floor(performance.now() - start), "ms");
const wave = audioToWav({
leftChannel: outLeft,
rightChannel: outRight,
sampleRate: sampleRate
});
fs.writeFileSync(args[2], new Buffer(wave));
process.exit();
Copyright © 2025 Spessasus Licensed under the Apache-2.0 License.
This project is in no way endorsed or otherwise affiliated with the MIDI Manufacturers Association, Creative Technology Ltd. or E-mu Systems, Inc., or any other organization mentioned. SoundFont® is a registered trademark of Creative Technology Ltd. All other trademarks are the property of their respective owners.