### 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); ```