32
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🏪JavaScriptのWeb Audio APIで「ファミマの入店音」を奏でる🏪

Last updated at Posted at 2024-12-28

概要

私の2023年のラストの記事で、🐸PowerShellのビープ音で「カエルの歌」を奏でる🐸という記事を書きました。その記事のセルフオマージュとなります。

今回はPowerShellではなく、JavaScriptのWeb Audio APIで同等の機能を実装してみます。

ぜひ、記事のコードを見比べながら読んでいただければと思います。

完成したもの

先に完成物です。ボタンを押すとファミマの入店音が流れます。
(音が出ますご注意ください)

See the Pen ファミマ入店 by ishi720 (@ishi720) on CodePen.

プログラム

音の再生する関数

/**
 * 指定した周波数と長さの音を再生する
 *
 * @param {number} frequency - 再生する音の周波数(Hz)
 * @param {number} duration - 再生する音の長さ(ミリ秒)
 * @returns {Promise<void>} 音の再生が終了した後に解決されるPromise
 */
function playTone(frequency, duration) {
    // Web Audio API コンテキストを作成する
    const context = new (window.AudioContext || window.webkitAudioContext)();
    // 音を生成するためのオシレーターノードを作成
    const oscillator = context.createOscillator();
    // 音量を制御するためのゲインノードを作成
    const gainNode = context.createGain();
    
    // オシレーターの周波数を引数で渡された値に設定
    oscillator.frequency.value = frequency;
    oscillator.type = "sine";
  
    // オシレーターノードをゲインノードに接続し、ゲインノードを出力に接続
    oscillator.connect(gainNode);
    gainNode.connect(context.destination);
    
    // 音の再生を開始
    oscillator.start();
  
    // 音量を徐々に下げていく
    gainNode.gain.setValueAtTime(1, context.currentTime);
    gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + duration / 1000);
  
    // 音の再生の終了
    oscillator.stop(context.currentTime + duration / 1000);
    
    return new Promise(resolve => setTimeout(resolve, duration));
}

公式ドキュメントを参考にして作成しています。

oscillator.typeを変えるとトライアングルような音やギターのような音を表現することができます。

パラメータは、いろいろ用意されているので、試してみてください!

  • sine
  • square
  • sawtooth
  • triangle
  • custom

こちらの公式ドキュメントを参照いただければと思います。
https://developer.mozilla.org/ja/docs/Web/API/OscillatorNode/type

ファミマのメロディを設定

/**
 * (非同期関数)ファミリーマートの入店音メロディを再生
 */
async function playMelody() {
    const Rhythm = 1000;

    // ファミマのメロディを再現
    await playTone(493.88, Rhythm / 4); // シ (B4)
    await playTone(392, Rhythm / 4); // ソ (G4)
    await playTone(294, Rhythm / 4); // レ (D4)
    await playTone(392, Rhythm / 4); // ソ (G4)
    await playTone(440, Rhythm / 4); // ラ (A4)
    await playTone(587.33, Rhythm / 4); // レ (D5)
    await new Promise(resolve => setTimeout(resolve, Rhythm / 4));
    await playTone(587.33, Rhythm / 4); // レ (D5)
    await playTone(440, Rhythm / 4); // ラ (A4)
    await playTone(493.88, Rhythm / 4); // シ (B4)
    await playTone(440, Rhythm / 4); // ラ (A4)
    await playTone(294, Rhythm / 4); // レ (D4)
    await playTone(392, Rhythm / 4); // ソ (G4)
}

基本的に、PowerShellで作成したときと同じ内容ですが、音符と休符を連続的に設定しているだけです。

//四分音符
await playTone(493.88, Rhythm / 4);
//四分休符
await new Promise(resolve => setTimeout(resolve, Rhythm / 4));

おわりに

powershellのBeep音で作成したときは、音がガビガビしていたのですが、JavaScriptのWeb Audio APIだと音がきれいですね。

また、WEB画面で動作するので、かなり可能性が広がりそうです。

ここまで読んでいただきありがとうございました。

2025年も頑張りましょう!

32
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?