-
-
Notifications
You must be signed in to change notification settings - Fork 12
Home
spessasus edited this page Jun 15, 2023
·
25 revisions
Welcome to the SpessaSynth wiki! This is the place where I try my best to explain the program.
The program is modular to allow it to for example, be sound only (IE. no visualizations).
Note that the wiki is still under construction, so some links might not be available right now.
- Synthetizer - Responsible for generating sound.
- Sequencer - Resposnible for playing the parsed MIDI sequence.
- Renderer - Responsible for rendering the falling notes and channels' waveforms.
- SoundFont2 - Responsible for parsing an SF2 file.
- MIDI parser - Responsible for parsing a MIDI file.
-
MIDI keyboard - Responsible for creating and managing the virtual keyboard on the screen. Also connects to physical MIDI devices using
WEB MIDI API
.
The program makes a heavy usage of the ES6 Modules!
To use the program as a library, simply copy the src
folder to your desired destination.
<h1>SpessaSynth demo</h1>
<p id="message">Please wait for the soundFont to load.</p>
<input type="file" id="midi_input" accept="audio/mid">
<!-- note the type="module" -->
<script src="main.js" type="module"></script>
// import the modules
import { MIDI } from "./src/js/midi_parser/midi_loader.js";
import { SoundFont2 } from "./src/js/soundfont/soundfont_parser.js";
import { Sequencer } from "./src/js/midi_player/sequencer/sequencer.js";
import { Synthetizer } from "./src/js/midi_player/synthetizer/synthetizer.js";
import {ShiftableByteArray} from "./src/js/utils/shiftable_array.js";
// load the soundfont
fetch("path/to/your/soundfont.sf2").then(async response => {
// the soundFont files are large, so we need to use readableStreams
// get the file size
let size = response.headers.get("content-length");
// get the reader
let reader = await (await response.body).getReader();
// indicates if the readableStream has ended
let done = false;
// initialize a new ShitabeByteArray(Uint8Array) of the size
let dataArray = new ShiftableByteArray(parseInt(size));
// index of the byte
let offset = 0;
do {
// read a fragment
let readData = await reader.read();
// if the stream is still open
if (readData.value) {
// put the read data into the array and move the offset
dataArray.set(readData.value, offset);
offset += readData.value.length;
}
// repeat until the stream has ended
done = readData.done;
}while (!done);
console.log("The soundfont has been loaded!");
document.getElementById("message").innerText = "SoundFont has been loaded!";
// parse the soundFont
const soundFont = new SoundFont2(dataArray);
// add an event listener
document.getElementById("midi_input").addEventListener("change", async event => {
// check if any files are added
if(!event.target.files[0])
{
return;
}
const file = event.target.files[0];
// convert the file to a byte array
const fileByteArray = new ShiftableByteArray(await file.arrayBuffer());
// parse the MIDI file
const parsedMidi = new MIDI(fileByteArray);
// create an audioContext
const context = new AudioContext();
// create the synthetizer
const synth = new Synthetizer(context.destination, soundFont);
// create the sequencer
const seq = new Sequencer(parsedMidi, synth);
// play
seq.play();
})
});
you can also use File
to pass the soundFont to the library, as long as you convert it to ShiftableByteArray
.
Tip
If you encounter any errors in this documentation, please open an issue!
Warning
Make sure you always update worklet_processor.min.js
along with the npm package!