### Minimal spessasynth_lib setup with WorkletSynthesizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/index.md
This JavaScript code demonstrates the minimal setup required to initialize the WorkletSynthesizer in a WebAudio context. It involves adding the worklet module and creating an instance of the synthesizer.
```javascript
audioContext.audioWorklet.addModule("path/to/worklet");
const synth = new WorkletSynthesizer(context);
```
--------------------------------
### Install spessasynth_lib using npm
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/index.md
This command installs the spessasynth_lib package as a dependency for your project using npm.
```shell
npm install --save spessasynth_lib
```
--------------------------------
### Implement MIDI Player with Spessasynth
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/simple-example.md
This example shows the HTML structure and JavaScript implementation required to play MIDI files. It utilizes the WorkletSynthesizer for audio synthesis and the Sequencer class to manage MIDI playback.
```html
```
```javascript
import { WorkletSynthesizer, Sequencer } from 'spessasynth_lib';
const audioContext = new AudioContext();
const synth = new WorkletSynthesizer(audioContext);
const sequencer = new Sequencer(synth);
async function init() {
const response = await fetch('soundbank.sf2');
const data = await response.arrayBuffer();
await synth.addSoundBank(data);
}
document.getElementById('midi-input').addEventListener('change', async (e) => {
const file = e.target.files[0];
const midiData = await file.arrayBuffer();
sequencer.load(midiData);
sequencer.play();
});
init();
```
--------------------------------
### Play a single note using WorkletSynthesizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/README.md
Demonstrates how to initialize the WorkletSynthesizer, load a soundbank, and trigger a MIDI note. This setup requires an AudioContext and the inclusion of the spessasynth_processor module.
```javascript
import { WorkletSynthesizer } from "spessasynth_lib";
// SF2, SF3, SFOGG and DLS files are all supported!
const sfont = await (await fetch("soundfont.sf3")).arrayBuffer();
const ctx = new AudioContext();
// make sure you copied the worklet processor!
await ctx.audioWorklet.addModule("./spessasynth_processor.min.js");
const synth = new WorkletSynthesizer(ctx);
await synth.soundBankManager.addSoundBank(sfont, "main");
await synth.isReady;
document.getElementById("button").onclick = async () => {
await ctx.resume();
synth.programChange(0, 48); // strings ensemble
synth.noteOn(0, 52, 127);
};
```
--------------------------------
### HTML Structure for Worker Synthesizer Example
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/worker-synth-example.md
The HTML file sets up the basic structure for the web page, including elements to display audio information and controls. It loads the main JavaScript file that interacts with the WorkerSynthesizer.
```html
Worker Synthesizer Example
Worker Synthesizer Example
This example demonstrates the use of the WorkerSynthesizer class.
```
--------------------------------
### Worker Synthesizer Initialization Example
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worker-synthesizer.md
Demonstrates the initialization of the WorkerSynthesizer. The worker script listens for the initial message to set up WorkerSynthesizerCore, while the main thread creates the AudioContext, registers the worklet, and instantiates WorkerSynthesizer, connecting it to the worker.
```javascript
// worker
let workerSynthCore;
// Wait for the first message with parameters
onmessage = (e) => {
if (e.ports[0]) {
// Initialize
workerSynthCore = new WorkerSynthesizerCore(
e.data,
e.ports[0],
postMessage.bind(this)
);
} else {
// Handle all other messages
void workerSynthCore.handleMessage(e.data);
}
};
```
```typescript
// main thread
// create audio context
const context = new AudioContext({
sampleRate: 44100
});
// register worklet
WorkerSynthesizer.registerPlaybackWorklet(context);
// create the worker
const worker = new Worker(
// make sure that your path is correct
new URL("worker.js", import.meta.url)
);
// create the synthesizer and bind it to the worker
const synth = new WorkerSynthesizer(context, worker.postMessage.bind(worker));
worker.onmessage = (e) => synth.handleWorkerMessage(e.data);
```
--------------------------------
### Start Offline Render
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worklet-synthesizer.md
Initiates an asynchronous offline audio rendering process using the synthesizer. Requires a configuration object containing MIDI data, sound banks, and optional sequencer settings.
```typescript
await synth.startOfflineRender(config);
```
--------------------------------
### Import WorkletSynthesizer (JavaScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/extra/working-with-browsers.md
A simple JavaScript example demonstrating how to import the WorkletSynthesizer from the spessasynth_lib package. This code is intended to be bundled for browser use.
```javascript
import { WorkletSynthesizer } from "spessasynth_lib";
console.log("yay, we have imported", WorkletSynthesizer);
```
--------------------------------
### HTML Structure for Advanced MIDI Player Controls
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/advanced-example.md
Defines the HTML structure for a MIDI player with added control buttons and a progress slider. This includes elements for file input, previous/pause/next song buttons, and a slider to indicate song progress.
```html
--8<-- "advanced_demo.html"
```
--------------------------------
### Initialize and Use WorkerSynthesizer for Audio Synthesis and Export
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Sets up the WorkerSynthesizer in a Web Worker for audio processing and demonstrates rendering audio to a WAV file and exporting SoundFont (SF2) and RMIDI files. It requires the spessasynth_lib and basic Web Worker setup.
```javascript
import { WorkerSynthesizer, Sequencer, audioBufferToWav } from "spessasynth_lib";
import { WorkerSynthesizerCore } from "spessasynth_lib";
// Worker file (worker.js)
let workerSynthCore;
onmessage = (e) => {
if (e.ports[0]) {
workerSynthCore = new WorkerSynthesizerCore(
e.data,
e.ports[0],
postMessage.bind(this)
);
} else {
void workerSynthCore.handleMessage(e.data);
}
};
// Main thread
const context = new AudioContext({ sampleRate: 44100 });
await WorkerSynthesizer.registerPlaybackWorklet(context);
const worker = new Worker(new URL("worker.js", import.meta.url));
const synth = new WorkerSynthesizer(context, worker.postMessage.bind(worker));
worker.onmessage = (e) => synth.handleWorkerMessage(e.data);
synth.connect(context.destination);
await synth.isReady;
await synth.soundBankManager.addSoundBank(sfBuffer, "main");
// Render audio to file
const audioBuffers = await synth.renderAudio(44100, {
extraTime: 2,
enableEffects: true,
loopCount: 0,
progressCallback: (progress, stage) => {
console.log(`Rendering: ${Math.floor(progress * 100)}% (Stage ${stage})`);
}
});
const wavBlob = audioBufferToWav(audioBuffers[0]);
// Export trimmed SoundFont
const sf2File = await synth.writeSF2({
trim: true,
bankID: "main",
progressFunction: (info) => console.log(`Saving: ${info.sampleName}`)
});
downloadFile(sf2File.binary, sf2File.fileName + ".sf2");
// Export RMIDI (embedded MIDI with sound bank)
const rmidiBuffer = await synth.writeRMIDI({ format: "sf2", trim: true });
downloadFile(rmidiBuffer, "embedded_midi.rmi");
```
--------------------------------
### Apply Reverb and Chorus Audio Effects with JavaScript
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
This example shows how to use standalone ReverbProcessor and ChorusProcessor from spessasynth_lib for audio effects. It covers creating processors with custom settings, connecting them in an audio chain, updating parameters at runtime, and cleaning up resources. Dependencies include ReverbProcessor, ChorusProcessor, and the Web Audio API's AudioContext.
```javascript
import { ReverbProcessor, ChorusProcessor } from "spessasynth_lib";
const context = new AudioContext();
const customImpulse = await loadCustomImpulseResponse();
const reverb = new ReverbProcessor(context, {
impulseResponse: customImpulse
});
const chorus = new ChorusProcessor(context, {
nodesAmount: 3,
defaultDelay: 0.02,
delayVariation: 0.005,
stereoDifference: 0.002,
oscillatorFrequency: 0.5,
oscillatorFrequencyVariation: 0.1,
oscillatorGain: 0.003
});
const source = context.createBufferSource();
source.connect(chorus.input);
chorus.connect(reverb.input);
reverb.connect(context.destination);
chorus.update({ oscillatorFrequency: 0.8, oscillatorGain: 0.005 });
reverb.update({ impulseResponse: newImpulse });
chorus.delete();
reverb.delete();
```
--------------------------------
### JavaScript for Piano Interaction and Sound Bank Loading
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/piano-example.md
Implements the interactive functionality of the clickable piano using JavaScript and the Spessasynth library. It sets up a 36-key keyboard, handles mouse pointer events for note on/off messages, and manages the uploading and loading of custom sound banks.
```javascript
const synth = new spessasynth.Synthesizer();
const pianoTable = document.getElementById('piano');
const soundbankInput = document.getElementById('soundbank');
const KEY_COUNT = 36;
const WHITE_KEYS = [
0, 2, 4, 5, 7, 9, 11,
12, 14, 16, 17, 19, 21, 23,
24, 26, 28, 29, 31, 33, 35
];
let currentNote = -1;
function createPiano() {
for (let i = 0; i < KEY_COUNT; i++) {
const keyElement = document.createElement('td');
keyElement.classList.add('key');
if (WHITE_KEYS.includes(i % 12)) {
keyElement.classList.add('white');
} else {
keyElement.classList.add('black');
}
keyElement.dataset.note = i;
pianoTable.appendChild(keyElement);
}
}
function handlePointerDown(event) {
const note = parseInt(event.target.dataset.note);
if (!isNaN(note)) {
synth.noteOn(note, 127);
currentNote = note;
}
}
function handlePointerUp() {
if (currentNote !== -1) {
synth.noteOff(currentNote);
currentNote = -1;
}
}
function handlePointerLeave() {
if (currentNote !== -1) {
synth.noteOff(currentNote);
currentNote = -1;
}
}
soundbankInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
synth.loadSoundBank(e.target.result);
};
reader.readAsArrayBuffer(file);
}
});
createPiano();
const keys = document.querySelectorAll('.key');
keys.forEach(key => {
key.addEventListener('pointerdown', handlePointerDown);
});
document.addEventListener('pointerup', handlePointerUp);
document.addEventListener('pointerleave', handlePointerLeave);
// Add hover effect for visual feedback
keys.forEach(key => {
key.addEventListener('pointerenter', (event) => {
if (event.buttons === 1 && currentNote !== -1) {
const note = parseInt(event.target.dataset.note);
if (!isNaN(note) && note !== currentNote) {
synth.noteOff(currentNote);
synth.noteOn(note, 127);
currentNote = note;
}
}
});
});
```
--------------------------------
### HTML Structure for Clickable Piano
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/piano-example.md
Defines the HTML structure for the clickable piano, including an input for uploading sound banks and a table to represent the piano keys. This serves as the visual foundation for the interactive piano.
```html
Spessasynth Piano
Spessasynth Piano
```
--------------------------------
### JavaScript Functionality for Advanced MIDI Player Controls
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/advanced-example.md
Implements the JavaScript logic to handle advanced MIDI player controls. This includes managing multiple file inputs, previous/pause/next song functionality, and updating a song progress slider based on playback.
```javascript
--8<-- "advanced_demo.js"
```
--------------------------------
### Main JavaScript for Worker Synthesizer Integration
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/worker-synth-example.md
This JavaScript code initializes the WorkerSynthesizer, passing a bound postMessage function from a created web worker. It utilizes the renderAudio method to synthesize and play audio sequences.
```javascript
import { WorkerSynthesizer } from "../dist/spessasynth.js";
const output = document.getElementById('output');
// Create a new Web Worker
const worker = new Worker("worker_synth_worker.js");
// Create a WorkerSynthesizer instance, passing the worker's postMessage bound to the worker
const synthesizer = new WorkerSynthesizer(worker.postMessage.bind(worker));
// Example sequence (MIDI notes)
const sequence = [
{ note: 60, time: 0, duration: 0.5 },
{ note: 62, time: 0.5, duration: 0.5 },
{ note: 64, time: 1, duration: 1 },
{ note: 60, time: 2, duration: 0.5 },
{ note: 62, time: 2.5, duration: 0.5 },
{ note: 64, time: 3, duration: 1 },
];
// Add the sequence to the synthesizer
sequence.forEach(note => synthesizer.addNote(note));
// Render and play the audio
async function playAudio() {
output.innerText = 'Rendering audio...';
const audioBuffer = await synthesizer.renderAudio();
output.innerText = 'Audio rendered. Playing...';
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start();
source.onended = () => {
output.innerText = 'Playback finished.';
};
}
playAudio();
```
--------------------------------
### Define Custom AudioWorkletNode Creator
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
An example of a custom creator function for an AudioWorkletNode, which can be passed to the SynthConfig object to customize node creation.
```javascript
((context: BaseAudioContext, name: string, options: AudioWorkletNodeOptions) => {
return new AudioWorkletNode(context, name, options);
});
```
--------------------------------
### Offline Audio Rendering Setup
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/render-audio-example.md
This snippet demonstrates the HTML and JavaScript implementation for offline audio rendering. It utilizes the WorkletSynthesizer to process MIDI and sound banks into an audio buffer, which is then converted to a WAV file.
```html
```
```javascript
// offline_audio.js
const synth = new WorkletSynthesizer();
synth.startOfflineRender(midiData, soundBank).then(audioBuffer => {
const wav = audioBufferToWav(audioBuffer);
// Handle the resulting wav blob
});
```
--------------------------------
### Web Worker Script for Audio Synthesis
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/worker-synth-example.md
This script defines the behavior of the web worker. It imports the Synthesizer class and handles messages from the main thread, forwarding them to the Synthesizer instance for audio processing.
```javascript
import { Synthesizer } from "../dist/spessasynth.js";
// Create a Synthesizer instance within the worker
const synthesizer = new Synthesizer();
// Listen for messages from the main thread
self.onmessage = (event) => {
const message = event.data;
// Forward messages to the synthesizer
synthesizer.handleMessage(message);
};
// You can also send messages back to the main thread if needed
// For example, to indicate when the worker is ready:
// self.postMessage({ type: 'ready' });
```
--------------------------------
### Connect Individual Outputs - JavaScript
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Connects individual MIDI channel outputs to an array of AudioNodes. Each node in the array corresponds to a specific channel, starting from the first channel.
```javascript
synth.connectIndividualOutputs(audioNodes);
```
```javascript
// create 16 analyzers and connect them
const analyzers = Array.from({ length: 16 }, () => context.createAnalyser());
synth.connectIndividualOutputs(analyzers);
```
--------------------------------
### Control Playback: Pause, Play
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/sequencer/index.md
Provides methods to control the playback of the MIDI sequence. The `pause` method stops playback temporarily, and the `play` method starts or resumes playback.
```typescript
sequencer.pause();
sequencer.play();
```
--------------------------------
### Handle Synthesizer Events with JavaScript
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
This snippet demonstrates how to add and remove event listeners for various synthesizer events like noteOn, noteOff, controllerChange, and programChange. It also shows how to set a time delay for events and provides examples of callback functions for visualizers and display updates. Dependencies include the synth object with its eventHandler.
```javascript
synth.eventHandler.addEvent("noteOn", "visualizer", (data) => {
highlightKey(data.midiNote, data.channel, data.velocity);
console.log(`Note ${data.midiNote} on channel ${data.channel}, velocity ${data.velocity}`);
});
synth.eventHandler.addEvent("noteOff", "visualizer", (data) => {
unhighlightKey(data.midiNote, data.channel);
});
synth.eventHandler.addEvent("controllerChange", "cc-display", (data) => {
updateControllerDisplay(data.channel, data.controllerNumber, data.controllerValue);
});
synth.eventHandler.addEvent("programChange", "program-display", (data) => {
displayProgram(data.channel, data.program, data.bank);
});
synth.eventHandler.addEvent("presetListChange", "preset-menu", (list) => {
populatePresetDropdown(list);
});
synth.eventHandler.timeDelay = 0.05;
synth.eventHandler.removeEvent("noteOn", "visualizer");
```
--------------------------------
### Load New Song List
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/sequencer/index.md
Loads a new list of MIDI songs into the sequencer. This method accepts an array of MIDI data, which can be parsed MIDI objects or binary ArrayBuffers with optional file names. It does not automatically start playback.
```typescript
sequencer.loadNewSongList(midiBuffers);
// midiBuffers is an array of:
// BasicMIDI | {
// binary: ArrayBuffer,
// fileName?: string
// }
```
--------------------------------
### Offline Audio Rendering with SpessaSynth and JavaScript
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
This code demonstrates how to render MIDI sequences to WAV audio files using SpessaSynth's WorkletSynthesizer and OfflineAudioContext. It covers parsing MIDI files, setting up the audio context, configuring the synthesizer, initiating the render process, and converting the output buffer to a WAV file for download. Dependencies include spessasynth_lib, spessasynth_core, and standard Web Audio API.
```javascript
import { WorkletSynthesizer, audioBufferToWav } from "spessasynth_lib";
import { BasicMIDI } from "spessasynth_core";
const midiBuffer = await midiFile.arrayBuffer();
const parsedMIDI = BasicMIDI.fromArrayBuffer(midiBuffer, midiFile.name);
const sampleRate = 44100;
const context = new OfflineAudioContext({
numberOfChannels: 2,
sampleRate: sampleRate,
length: sampleRate * (parsedMIDI.duration + 1)
});
await context.audioWorklet.addModule("spessasynth_processor.min.js");
const synth = new WorkletSynthesizer(context, { enableEventSystem: false });
synth.connect(context.destination);
await synth.startOfflineRender({
midiSequence: parsedMIDI,
soundBankList: [{ bankOffset: 0, soundBankBuffer: sfBuffer }],
loopCount: 0
});
await synth.isReady;
const outputBuffer = await context.startRendering();
const wavFile = audioBufferToWav(outputBuffer, true, 0, {
title: parsedMIDI.getName(),
artist: "SpessaSynth",
album: "MIDI Renders"
});
const url = URL.createObjectURL(wavFile);
const link = document.createElement("a");
link.href = url;
link.download = parsedMIDI.getName() + ".wav";
link.click();
```
--------------------------------
### MIDI File Playback with Sequencer
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Illustrates how to use the Sequencer class to play MIDI files. This includes setting up a synthesizer, loading MIDI files into a playlist, controlling playback (play, pause, seek, speed, loop), and handling playback events. It also shows how to retrieve MIDI data from the sequencer.
```javascript
import { Sequencer, WorkletSynthesizer } from "spessasynth_lib";
// Setup synthesizer (see above)
const context = new AudioContext();
await context.audioWorklet.addModule("spessasynth_processor.min.js");
const synth = new WorkletSynthesizer(context);
synth.connect(context.destination);
await synth.soundBankManager.addSoundBank(sfBuffer, "main");
// Create sequencer and connect to synthesizer
const sequencer = new Sequencer(synth, {
skipToFirstNoteOn: true,
initialPlaybackRate: 1.0
});
// Load MIDI files into a playlist
const midiFiles = [];
for (const file of uploadedFiles) {
const buffer = await file.arrayBuffer();
midiFiles.push({ binary: buffer, fileName: file.name });
}
sequencer.loadNewSongList(midiFiles);
// Playback controls
sequencer.play(); // Start playback
sequencer.pause(); // Pause playback
sequencer.currentTime = 30; // Seek to 30 seconds
sequencer.playbackRate = 1.5; // 1.5x speed
sequencer.loopCount = Infinity; // Loop forever
sequencer.songIndex = 2; // Jump to third song
// Listen for events
sequencer.eventHandler.addEvent("songChange", "my-listener", (midiData) => {
console.log("Now playing:", midiData?.getName());
console.log("Duration:", sequencer.duration, "seconds");
});
// Get current MIDI data
const midi = await sequencer.getMIDI();
console.log("Track count:", midi.tracksAmount);
```
--------------------------------
### Get Master Parameter - JavaScript
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Retrieves a master parameter from the synthesizer. The specific value returned depends on the 'type' parameter provided. This function is synchronous.
```javascript
synth.getMasterParameter(type);
```
```javascript
// Get the current MIDI system
console.log(synth.getMasterParameter("midiSystem"));
```
--------------------------------
### Real-time MIDI Control with Synthesizer Methods
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Demonstrates various real-time MIDI control methods available through the synthesizer object. This includes note on/off, program and controller changes, pitch manipulation, and channel configuration. These methods allow for dynamic interaction with the synthesized audio.
```javascript
// Note control
synth.noteOn(0, 60, 127); // Channel 0, middle C, max velocity
synth.noteOn(0, 64, 100); // Channel 0, E, velocity 100
synth.noteOff(0, 60); // Release middle C
synth.noteOff(0, 64, true); // Force stop E immediately
synth.stopAll(true); // Panic - stop all notes
// Program and bank selection
synth.programChange(0, 48); // Set channel 0 to Strings Ensemble
synth.controllerChange(0, 0, 8); // Bank Select MSB = 8
synth.controllerChange(0, 32, 0); // Bank Select LSB = 0
synth.programChange(0, 25); // Steel Guitar from bank 8
// Expression and dynamics
synth.controllerChange(0, 7, 100); // Volume (CC 7)
synth.controllerChange(0, 11, 80); // Expression (CC 11)
synth.controllerChange(0, 10, 0); // Pan hard left
synth.controllerChange(0, 1, 64); // Modulation wheel
synth.channelPressure(0, 64); // Channel aftertouch
synth.polyPressure(0, 60, 100); // Per-note pressure on C
// Pitch control
synth.pitchWheel(0, 16383); // Pitch bend up (0-16384, 8192=center)
synth.pitchWheelRange(0, 12); // Set pitch bend range to +/-12 semitones
synth.transposeChannel(0, 2); // Transpose up 2 semitones
synth.transposeChannel(1, -0.5); // Transpose down 50 cents
// Channel configuration
synth.setDrums(9, true); // Set channel 9 as drum channel
synth.muteChannel(2, true); // Mute channel 2
synth.lockController(0, 7, true); // Lock volume control on channel 0
// System Exclusive messages
synth.systemExclusive([0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7]); // GS Reset
```
--------------------------------
### Get MIDI Data Asynchronously
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/sequencer/index.md
Asynchronously retrieves the complete MIDI data for the current sequence. This method is important for accessing the raw sequence information, including track data.
```javascript
const data = await sequencer.getMIDI();
```
--------------------------------
### Initialize ReverbProcessor
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/reverb-processor.md
Creates a new instance of the ReverbProcessor. Requires a BaseAudioContext and an optional configuration object.
```typescript
const reverbProcessor = new ReverbProcessor(context, config);
```
--------------------------------
### Configure npm Scripts for Building (JSON)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/extra/working-with-browsers.md
This JSON snippet shows how to add a 'build' script to your package.json file that executes the build.sh script. This allows you to conveniently build your project using 'npm run build'.
```json
{
"scripts": {
"build": "./build.sh"
}
}
```
--------------------------------
### Real-time MIDI Synthesis with WorkletSynthesizer
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Demonstrates real-time MIDI playback using the WorkletSynthesizer, which utilizes AudioWorklets for stable audio processing. It covers setting up the AudioContext, initializing the synthesizer with effects, loading sound banks, and playing notes programmatically. Cleanup is handled via the 'beforeunload' event.
```javascript
import { WorkletSynthesizer } from "spessasynth_lib";
// Create an AudioContext and add the worklet module
const context = new AudioContext({ sampleRate: 44100 });
await context.audioWorklet.addModule("spessasynth_processor.min.js");
// Initialize the synthesizer
const synth = new WorkletSynthesizer(context, {
initializeReverbProcessor: true,
initializeChorusProcessor: true,
enableEventSystem: true
});
synth.connect(context.destination);
// Load a SoundFont file
const sfResponse = await fetch("soundfont.sf2");
const sfBuffer = await sfResponse.arrayBuffer();
await synth.soundBankManager.addSoundBank(sfBuffer, "main");
// Wait for synthesizer to be ready
await synth.isReady;
// Play notes programmatically
document.getElementById("playButton").onclick = async () => {
await context.resume();
synth.programChange(0, 0); // Set channel 0 to Acoustic Grand Piano
synth.noteOn(0, 60, 100); // Play middle C on channel 0
setTimeout(() => synth.noteOff(0, 60), 1000); // Stop after 1 second
};
// Clean up when done
window.addEventListener("beforeunload", () => synth.destroy());
```
--------------------------------
### Send System Exclusive Message
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Handles MIDI System Exclusive (SysEx) messages. The data array should exclude the 0xF0 start byte, and an optional channel offset can be provided to address channels beyond the standard 16.
```js
synth.systemExclusive([
0x41, 0x10, 0x42, 0x12, 0x40, 0x1a, 0x15, 0x01, 0x10, 0xf7
]);
synth.systemExclusive(
[0x41, 0x10, 0x42, 0x12, 0x40, 0x1a, 0x15, 0x01, 0x10, 0xf7],
10
);
```
--------------------------------
### Initialize ChorusProcessor (TypeScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/chorus-processor.md
Initializes a new ChorusProcessor instance. Requires an AudioContext and an optional configuration object. The configuration allows customization of delay nodes, oscillator frequencies, and stereo differences.
```typescript
const chorusProcessor = new ChorusProcessor(context, config);
```
--------------------------------
### Manage Multiple Sound Banks with Sound Bank Manager
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Illustrates how to use the Sound Bank Manager to add, prioritize, and remove multiple sound banks. This enables layered instruments and dynamic switching between different sound sets. It also shows how to subscribe to preset list changes.
```javascript
// Access via synthesizer
const manager = synth.soundBankManager;
// Add sound banks with different IDs and priorities
const mainSF = await fetch("main.sf2").then(r => r.arrayBuffer());
const extraSF = await fetch("extra.sf3").then(r => r.arrayBuffer());
await manager.addSoundBank(mainSF, "main", 0); // Bank offset 0
await manager.addSoundBank(extraSF, "extra", 128); // Bank offset 128
// Set priority order (first bank overrides matching presets in later banks)
manager.priorityOrder = ["extra", "main"];
// Remove a sound bank
await manager.deleteSoundBank("extra");
// Listen for preset list changes
synth.eventHandler.addEvent("presetListChange", "preset-listener", (presetList) => {
console.log("Available presets:", presetList);
presetList.forEach(preset => {
console.log(`Bank ${preset.bank}, Program ${preset.program}: ${preset.presetName}`);
});
});
```
--------------------------------
### Initialize WorkletSynthesizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worklet-synthesizer.md
Initializes a new instance of the WorkletSynthesizer by providing an AudioContext and optional configuration. Requires the worklet processor module to be loaded into the audio context prior to instantiation.
```typescript
const context = new AudioContext({
sampleRate: 44100
});
await context.audioWorklet.addModule("spessasynth_processor.min.js");
const synth = new WorkletSynthesizer(context);
```
--------------------------------
### JavaScript for SpessaSynth Visualizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/visualizer-example.md
This JavaScript code initializes the SpessaSynth synthesizer, sets up audio context, connects individual audio nodes for visualization, and implements event handlers for 'noteOn' and 'noteOff' events to visually indicate key presses on the keyboard. It requires the SpessaSynth library and a canvas element in the HTML.
```javascript
const synth = new SpessaSynth();
const audioContext = synth.audioContext;
const canvas = document.getElementById('visualizerCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth * 0.8;
canvas.height = 300;
const audioNodes = {};
// Connect individual outputs for visualization
synth.connectIndividualOutputs(audioNodes);
// Function to draw the visualization (e.g., frequency data)
function drawVisualization(analyserNode) {
const bufferLength = analysererNode.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
analyserNode.getByteFrequencyData(dataArray);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgb(0, 0, 0)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const barWidth = (canvas.width / bufferLength) * 2.5;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const barHeight = dataArray[i] / 255 * (canvas.height / 2);
ctx.fillStyle = 'rgb(0, 255, 0)';
ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
requestAnimationFrame(() => drawVisualization(analyserNode));
}
// Start visualization if AnalyserNode is available
if (audioNodes.analyser) {
drawVisualization(audioNodes.analyser);
}
// Event handler for note on
synth.eventHandler.addEvent("noteOn", (event) => {
const keyElement = document.querySelector(`.key[data-note='${event.note}']`);
if (keyElement) {
keyElement.classList.add('active');
}
});
// Event handler for note off
synth.eventHandler.addEvent("noteOff", (event) => {
const keyElement = document.querySelector(`.key[data-note='${event.note}']`);
if (keyElement) {
keyElement.classList.remove('active');
}
});
// Add event listeners to keyboard keys
document.querySelectorAll('.key').forEach(key => {
key.addEventListener('mousedown', () => {
const note = key.dataset.note;
synth.play(note);
key.classList.add('active');
});
key.addEventListener('mouseup', () => {
const note = key.dataset.note;
synth.stop(note);
key.classList.remove('active');
});
key.addEventListener('mouseleave', () => {
const note = key.dataset.note;
synth.stop(note);
key.classList.remove('active');
});
});
```
--------------------------------
### Bundle and Minify JavaScript with esbuild (Shell Command)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/extra/working-with-browsers.md
This command uses esbuild to bundle, minify, and generate sourcemaps for a JavaScript file intended for browser execution. It specifies the format as ES module and the platform as browser.
```shell
esbuild main.js --bundle --minify --sourcemap=linked --format=esm --platform=browser --outfile=main.min.js
```
--------------------------------
### Configure Synthesizer Log Levels
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Demonstrates how to set the logging verbosity for the synthesizer processor using the setLogLevel method.
```javascript
// Enable all logs
synth.setLogLevel(true, true, true);
```
--------------------------------
### Export AudioBuffer to WAV File
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Convert AudioBuffer objects into downloadable WAV files. Supports metadata injection, loop point definition, and multi-channel extraction.
```javascript
import { audioBufferToWav } from "spessasynth_lib";
// Basic conversion with normalization
const wavBlob = audioBufferToWav(audioBuffer, true);
// Export with metadata
const wavWithMeta = audioBufferToWav(audioBuffer, true, 0, {
title: "My MIDI Render",
artist: "SpessaSynth User",
album: "MIDI Collection",
genre: "Electronic"
});
// Export with loop points for seamless looping
const loopingWav = audioBufferToWav(audioBuffer, true, 0, {}, {
start: 5.0,
end: 30.0
});
// Export specific channels from multi-channel buffer
const channel0Wav = audioBufferToWav(audioBuffer, true, 0, {}, undefined, 2);
// Create download link
const url = URL.createObjectURL(wavBlob);
const a = document.createElement("a");
a.href = url;
a.download = "output.wav";
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);
```
--------------------------------
### Initialize MIDI Device Handler
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/midi/web-midi-api.md
Initializes the connection to physical MIDI devices. This method is asynchronous and returns a MIDIDeviceHandler instance, throwing an error if initialization fails.
```javascript
MIDIDeviceHandler.createMIDIDeviceHandler();
```
--------------------------------
### Initialize Web MIDI Link Handler (JavaScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/midi/web-midi-link.md
Initializes the Web MIDI Link handler, connecting it to a synthesizer instance. The handler listens for MIDI messages formatted as 'midi,xx,yy,zz' from the parent window and forwards them to the connected synthesizer. Requires a synthesizer instance (WorkletSynthesizer or WorkerSynthesizer) as input.
```javascript
new WebMIDILinkHandler(synth);
```
--------------------------------
### Initialize Sequencer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/sequencer/index.md
Initializes a new Sequencer instance. It requires a Synthesizer object and an optional options object for configuration. Options include skipping to the first note on and setting the initial playback rate.
```typescript
const sequencer = new Sequencer(synth, options);
// options can include:
// {
// skipToFirstNoteOn?: boolean,
// initialPlaybackRate?: number
// }
```
--------------------------------
### Importing Audio Worklet Module
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/importing-the-worklet.md
Demonstrates the correct way to load the audio worklet module using a URL relative to the current module. This approach ensures compatibility with modern bundlers like WebPack by utilizing import.meta.url.
```typescript
await context.audioWorklet.addModule(
new URL("./spessasynth_processor.min.js", import.meta.url)
);
```
--------------------------------
### Copy Worklet Processor and Bundle with esbuild (Shell Script)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/extra/working-with-browsers.md
This shell script automates the process of copying the spessasynth_lib worklet processor to a public directory and then uses esbuild to bundle the main application code for browser use. It includes minification and sourcemap generation.
```shell
# Copy the worklet
cp node_modules/spessasynth_lib/dist/spessasynth_processor.min.js public/spessasynth_processor.min.js
# Your build script here
esbuild --bundle --minify --sourcemap=linked --platform=browser index.js --outfile=index.min.js
```
--------------------------------
### Integrate Physical MIDI Devices with MIDIDeviceHandler
Source: https://context7.com/spessasus/spessasynth_lib/llms.txt
Utilize the Web MIDI API to connect and disconnect MIDI keyboards and output devices. This handler allows routing of input signals to the synthesizer and sequencer playback to external hardware.
```javascript
import { MIDIDeviceHandler } from "spessasynth_lib";
// Initialize MIDI device handler
const midiHandler = await MIDIDeviceHandler.createMIDIDeviceHandler();
// List available MIDI inputs
console.log("MIDI Inputs:");
midiHandler.inputs.forEach((input, id) => {
console.log(` ${id}: ${input.name} (${input.manufacturer})`);
});
// List available MIDI outputs
console.log("MIDI Outputs:");
midiHandler.outputs.forEach((output, id) => {
console.log(` ${id}: ${output.name} (${output.manufacturer})`);
});
// Connect a MIDI keyboard to the synthesizer
const keyboardInput = midiHandler.inputs.get("input-0");
if (keyboardInput) {
keyboardInput.connect(synth);
console.log(`Connected ${keyboardInput.name} to synthesizer`);
}
// Route sequencer playback to external MIDI device
const externalSynth = midiHandler.outputs.get("output-0");
if (externalSynth) {
externalSynth.connect(sequencer);
console.log(`Routing playback to ${externalSynth.name}`);
}
// Disconnect devices
keyboardInput?.disconnect(synth);
externalSynth?.disconnect(sequencer);
```
--------------------------------
### Link Bundled JavaScript to HTML (HTML)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/extra/working-with-browsers.md
This HTML snippet shows how to include the bundled and minified JavaScript file (main.min.js) in your web page using a script tag. It specifies the type as 'module' to ensure correct execution of ES modules.
```html
```
--------------------------------
### Tune MIDI Keys
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Applies custom tuning to specific MIDI keys within a program using the MIDI Tuning Standard. Allows for precise pitch adjustment per note using source and target pitch mapping.
```js
synth.tuneKeys(81, [
{ sourceKey: 60, targetPitch: 72.5778 },
{ sourceKey: 78, targetPitch: 64.12 }
]);
```
--------------------------------
### Initialize WorkerSynthesizerCore
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worker-synthesizer.md
Initializes the core worker-side synthesizer logic. It requires configuration data, a message port for the worklet, a callback for main thread communication, and an optional compression function for SF3 bank writing.
```typescript
const workerSynthCore = new WorkerSynthesizerCore(
synthesizerConfiguration,
workletMessagePort,
mainThreadCallback,
compressionFunction
);
```
--------------------------------
### HTML Structure for SpessaSynth Visualizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/getting-started/visualizer-example.md
This HTML file sets up the basic structure for the SpessaSynth visualizer, including the canvas element where visualizations will be rendered and the 'keyboard' elements for user interaction. It serves as the foundation for the visual components of the demo.
```html
SpessaSynth Visualizer
SpessaSynth Visualizer
C
D
E
F
G
A
B
C
```
--------------------------------
### Initialize WorkerSynthesizer
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worker-synthesizer.md
Initializes the WorkerSynthesizer with an AudioContext, a postMessage function for the worker, and optional configuration. The postMessage function can be intercepted for message handling.
```typescript
const synth = new WorkerSynthesizer(context, workerPostMessage, config);
```
--------------------------------
### Update ChorusProcessor Configuration (TypeScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/chorus-processor.md
Updates the configuration of an existing ChorusProcessor instance. The provided configuration object can be partial, allowing specific parameters to be modified without re-initializing the entire effect.
```typescript
chorusProcessor.update(config);
```
--------------------------------
### Connect and Disconnect MIDI Outputs
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/midi/web-midi-api.md
Manages the connection between a sequencer and a LibMIDIOutput. Connecting allows the sequencer to play back MIDI files through the output, while disconnecting redirects output back to the attached synthesizer.
```typescript
output.connect(seq);
output.disconnect(seq);
```
--------------------------------
### POST synth.eventHandler.addEvent
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/synth-event-handler.md
Registers a new event listener to the synthesizer's event system.
```APIDOC
## POST synth.eventHandler.addEvent
### Description
Registers a callback function to be executed when a specific synthesizer event occurs.
### Method
POST
### Endpoint
synth.eventHandler.addEvent(name, id, callback)
### Parameters
#### Path Parameters
- **name** (string) - Required - The type of event to listen for (e.g., "noteOn").
- **id** (string) - Required - A unique identifier for the listener used for management.
- **callback** (function) - Required - The function to execute when the event triggers. Receives an object containing event-specific data.
### Request Example
```js
synth.eventHandler.addEvent("noteOn", "note-on-listener", (data) => {
console.log(`Note ${data.midiNote} played.`);
});
```
### Response
#### Success Response (void)
- Returns nothing; registers the listener internally.
```
--------------------------------
### Apply Channel Pressure (JavaScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Applies pressure to a specified MIDI channel, commonly used to control vibrato depth. The pressure value ranges from 0 (no pressure) to 127 (maximum pressure). Optional 'eventOptions' can be provided for advanced control.
```javascript
synth.channelPressure(channel, pressure, eventOptions);
// Example:
// set channel 1 pressure to 64 (middle)
synth.channelPressure(1, 64);
```
--------------------------------
### Render Audio with Spessasynth
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/worker-synthesizer.md
Renders the current song in the connected sequencer to Float32 buffers within the worker, pausing playback during rendering. It requires a sample rate and accepts optional 'renderOptions' for fadeout time, channel separation, loop count, progress tracking, parameter preservation, effect enablement, and sequencer selection. The function returns an array of AudioBuffers.
```TypeScript
const rendered = synth.renderAudio(sampleRate, renderOptions);
// sampleRate - the sample rate to use, in Hertz.
// renderOptions - an optional configuration for writing the file. Described below:
// - extraTime - extra fadeout time after the song finishes, in seconds.
// - separateChannels - if channels should be rendered separately.
// - loopCount - the amount of times to loop the song.
// - progressCallback - the function that tracks the rendering progress. It takes two arguments:
// - progress - mapped 0 to 1.
// - stage - 0 is a dry pass, 1 is adding effects.
// - preserveSynthParams - if the current parameters of the synthesizer should be preserved.
// - enableEffects - if the effects should be enabled.
// - sequencerID - which sequencer to render. Defaults to the first one (0).
//
The returned value is an array of `AudioBuffer`s:
// A single audioBuffer if separate channels were not enabled, otherwise 16.
```
--------------------------------
### Set MIDI Controller Value (JavaScript)
Source: https://github.com/spessasus/spessasynth_lib/blob/master/docs/synthesizer/basic-synthesizer.md
Sets a specified MIDI controller on a given channel to a specific value. Supports an optional 'force' parameter to override locks or GM mode restrictions, and 'eventOptions' for advanced configurations. Useful for controlling various synth parameters like volume, pan, or modulation.
```javascript
synth.controllerChange(
channel,
controllerNumber,
controllerValue,
(force = false),
eventOptions
);
// Example:
// set controller 10 (Channel Pan) on channel 2 to 127 (Hard right)
synth.controllerChange(2, 10, 127);
```