Skip to content

Clickable Piano Example

See this demo live

This example creates a simple piano to be played with the mouse. It also allows uploading a sound bank instead of using a built-in one.

We need to add an input for uploading the sound bank and the table for our piano.

piano.html
<label for="sound_bank_input">Upload the sound bank.</label>
<input accept=".sf2, .sf3, .dls" id="sound_bank_input" type="file" />
<table>
    <tr id="piano"></tr>
</table>
<!-- note the type="module" -->
<script src="piano.js" type="module"></script>

We create a 36-key keyboard and add pointer events to it which control the note-on and note-off messages.

piano.js
// Import the modules
import { WorkletSynthesizer } from "../../src/index.js";
import { EXAMPLE_WORKLET_PATH } from "../examples_common.js";

document
    .querySelector("#sound_bank_input")
    .addEventListener("change", async (event) => {
        // Check if there's a file uploaded
        if (!event.target.files[0]) {
            return;
        }
        const file = event.target.files[0];
        const sfFile = await file.arrayBuffer(); // Convert to array buffer
        // Create the context and add audio worklet
        const context = new AudioContext();
        await context.audioWorklet.addModule(EXAMPLE_WORKLET_PATH);
        // Create the synthesizer
        const synth = new WorkletSynthesizer(context);
        synth.connect(context.destination);
        await synth.isReady;
        await synth.soundBankManager.addSoundBank(sfFile, "main");
        // Create a 36-key piano
        const piano = document.querySelector("#piano");
        for (let index = 0; index < 36; index++) {
            /**
             * @type {HTMLElement}
             */
            const key = document.createElement("td");
            key.style.background = "white";
            key.style.height = "10em";
            key.style.width = "2em";
            key.style.margin = "0.2em";
            piano.append(key);
            // Add mouse events
            key.addEventListener("pointerdown", () => {
                // Key press: play a note
                synth.noteOn(0, 46 + index, 127);
                key.style.background = "red";
            });
            key.addEventListener("pointerup", () => {
                // Key release: stop a note
                synth.noteOff(0, 46 + index);
                key.style.background = "white";
            });
            key.addEventListener("pointerleave", key.onpointerup);
        }
    });