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

# 概要

私の2023年のラストの記事で、[🐸PowerShellのビープ音で「カエルの歌」を奏でる🐸](https://qiita.com/ishi720/items/e23e8d6addc62b1951a3)という記事を書きました。その記事のセルフオマージュとなります。

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

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


# 完成したもの

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

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="KwPvpaY" data-pen-title="ファミマ入店音" data-user="ishi720" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ishi720/pen/KwPvpaY">
  ファミマ入店</a> by ishi720 (<a href="https://codepen.io/ishi720">@ishi720</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


# プログラム 

## 音の再生する関数

```javascript
/**
 * 指定した周波数と長さの音を再生する
 *
 * @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));
}
```



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

https://developer.mozilla.org/ja/docs/Web/API/OscillatorNode

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

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

- sine
- square
- sawtooth
- triangle
- custom

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

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

```javascript
/**
 * （非同期関数）ファミリーマートの入店音メロディを再生
 */
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で作成したときと同じ内容ですが、音符と休符を連続的に設定しているだけです。

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



# おわりに

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

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

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

2025年も頑張りましょう！