Sound frequencies of 88 piano keys and Web Audio API

The frequencies of the notes of the 88 piano keys are tabulated. The sounds with these frequencies are output by the Web Audio API’s OscillatorNode.

The frequency of a note doubles in an octave and the frequency of the 12 notes within an octave increases by a factor of $\sqrt[12]{2}=2^{\frac1{12}}$. Therefore, when the note A4 (4th octave A) is 440 Hz, the frequency of the note in the nth key of the 88 keys is expressed by the following formula.

\[f(n) = 27.5 \cdot 2^{\frac{n-1}{12}}\]

The 27.5 Hz in the above equation is the frequency of the note A0 (the 0th octave A). Going down one octave halves the frequency of the note. When the note A4 (the 4th octave A) is 440 Hz, A3 is 220 Hz, A2 is 110 Hz, A1 is 55 Hz and A0 is 27.5 Hz.

The following table was generated with JavaScript. The sound is not a piano sound. It is output with Web Audio API’s OscillatorNode by specifying a sine wave parameter.

Click the button to play the sound. Pay attention to the volume (especially high frequency sound).
Click the button again to turn off the sound.

The table above was generated with the following JavaScript. The generated HTML uses Bootstrap (v5.0.2). $\flat$ is displayed using Simple MathJax, a WordPress plugin that displays mathematical formulas.

<script type="text/javascript">

// -------------------------------------------------------
// Output Table
// -------------------------------------------------------

const key_names =
[
    ["ラ", "", "A", ""],
    ["ラ#", "シ$\\flat$", "A#", "B$\\flat$"],
    ["シ", "","B", ""],
    ["ド", "","C", ""],
    ["ド#", "レ$\\flat$","C#", "D$\\flat$"],
    ["レ", "","D", ""],
    ["レ#", "ミ$\\flat$","D#", "E$\\flat$"],
    ["ミ", "","E", ""],
    ["ファ", "","F", ""],
    ["ファ#", "ソ$\\flat$","F#", "G$\\flat$"],
    ["ソ", "", "G", ""],
    ["ソ#", "ラ$\\flat$", "G#", "A$\\flat$"]
];

let table_html = "<table class='table table-striped'>";
table_html += "<tr>";
table_html += "<td>Keyboard<br/>number</td>";
table_html += "<td>Frequency (Hz)</td>";
table_html += "<td colspan='4'>Names of <br/>musical scales</td>";
table_html += "<td>Hear the sound</td>";
table_html += "</tr>";

for (n = 0; n < 88; n++) {

    const frequency = getAudioFrequency(n);

    let octave = parseInt(n/12);
    if (n % 12 >= 3) {
        octave++;
    }

    const key_japanese = key_names[n % 12][0] + octave;
    let key_japanese_flat = "";

    if (key_names[n % 12][1] != "") {
        key_japanese_flat = key_names[n % 12][1] + octave;
    }

    const key_english = key_names[n % 12][2] + octave;
    let key_english_flat = "";
    if (key_names[n % 12][3] != "") {
        key_english_flat = key_names[n % 12][3] + octave;
    }

    const button_id = "start-stop-oscillator-" + n;
    const button = "<button class='btn btn-warning' id='" + button_id + "'/>";

    const keyboard_number = n + 1;
    table_html += "<tr>";
    table_html += "<td>" + keyboard_number + "</td>";
    table_html += "<td>" + frequency.toFixed(3) + "</td>";
    table_html += "<td>" + key_japanese + "</td>";
    table_html += "<td>" + key_japanese_flat + "</td>";
    table_html += "<td>" + key_english + "</td>";
    table_html += "<td>" + key_english_flat + "</td>";
    table_html += "<td>" + button + "</td>"
    table_html += "</tr>";
}

table_html += "</table>";
document.getElementById('piano-keys-table').innerHTML = table_html;

// -------------------------------------------------------
// Codes for Web Audio API
// -------------------------------------------------------

// create web audio api context
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

const oscillatorMap = new Map();
const isPlayingMap = new Map();

for (n = 0; n < 88; n++) {
    const frequency = getAudioFrequency(n);
    const buttonText = 'audio (sine, ' + frequency.toFixed(3) + 'Hz)';
    const button_id = "start-stop-oscillator-" + n;
    CreateAudioOscillator(buttonText, button_id, 'sine', frequency);
}

// -------------------------------------------------------
// functions
// -------------------------------------------------------

function getAudioFrequency(n) {
    return 27.5 * ( Math.pow( Math.pow(2, 1/12), n) );
}

function CreateAudioOscillator(buttonText, buttonID, oscillatorType, frequency) {

    const button = document.getElementById(buttonID);
    button.textContent = buttonText;

    button.addEventListener("click", () => {

        let oscillator = oscillatorMap.get(buttonID);
        let isPlaying = isPlayingMap.get(buttonID);

        if (isPlaying === undefined) {
            isPlaying = false;
        }

        if (isPlaying === false) {
            oscillator = audioCtx.createOscillator();
            oscillator.type = oscillatorType;
            oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime);
            oscillator.connect(audioCtx.destination);
            oscillator.start();
            isPlaying = true;

            button.textContent = buttonText + " - playing";
        } else {
            oscillator.stop();
            isPlaying = false;

            button.textContent = buttonText;
        }

        oscillatorMap.set(buttonID, oscillator);
        isPlayingMap.set(buttonID, isPlaying);

    });
}
</script>

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA