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.getElementById("sound_bank_input").onchange = async (e) => {
    // check if there's a file uploaded
    if (!e.target.files[0]) {
        return;
    }
    const file = e.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.getElementById("piano");
    for (let i = 0; i < 36; i++) {
        /**
         * @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.appendChild(key);
        // add mouse events
        key.onpointerdown = () => {
            // key press: play a note
            synth.noteOn(0, 46 + i, 127);
            key.style.background = "red";
        };
        key.onpointerup = () => {
            // key release: stop a note
            synth.noteOff(0, 46 + i);
            key.style.background = "white";
        };
        key.onpointerleave = key.onpointerup;
    }
};