JavaScriptのAudioContextを使えばmp3なしで音が作成可能

AudioContextとは

AudioContextとはJavaScriptを使用してWebブラウザで高度なオーディオ操作するためのインターフェースです。

このAPIを利用すると、オーディオデータの生成、加工、解析、および再生が可能になります。

mp3などの音声ファイルが不要なので、音を鳴らしたい場合でも軽量なJavaScriptコードのみで実装できます。

例えば深夜のテレビの放送休止音(ピーーー)を作成して、3秒後に停止する処理をJavaScriptで書くと以下のようになります。(1000Hzの周波数を使用)

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const oscillator = audioCtx.createOscillator()
oscillator.connect(audioCtx.destination)
oscillator.type = 'sine'
oscillator.frequency.setValueAtTime(1000, audioCtx.currentTime)
oscillator.start()
oscillator.stop(audioCtx.currentTime + 3) // 3秒後に停止

音階の周波数の数値は決まっていて、例えばドレミファソラシド(C4からC5)の音を出すにはforEachを使って順番に出します。

const audioContext = new (window.AudioContext || window.webkitAudioContext)()

// 周波数に対応する音階(ドレミファソラシド C4からC5まで)
const frequencies = [261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25]

// 指定した周波数で音を鳴らす関数
function playTone(freq) {
  const oscillator = audioContext.createOscillator()
  oscillator.frequency.setValueAtTime(freq, audioContext.currentTime)
  oscillator.type = 'sine'

  const gainNode = audioContext.createGain()
  gainNode.gain.setValueAtTime(1, audioContext.currentTime)
  gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 1.5)
  oscillator.connect(gainNode)
  gainNode.connect(audioContext.destination)
  oscillator.start()
  oscillator.stop(audioContext.currentTime + 1.5)
}

// 再生
frequencies.forEach((freq, index) => {
  setTimeout(() => playTone(freq), 500 * index)
})

周波数の数値を指定して音を作成するので、長い曲のような複雑な音は作れません。

処理が終わったときに鳴らすと便利

このような処理は、処理が終了した時に音を鳴らすことで特に便利です。

JavaScriptの処理が完了したことを音で知らせることで、画面を見なくても処理完了がわかります。

私の場合、JavaScriptのコードによっては、処理完了時に「ピンポーン」という音を鳴らしています。

const audioCtx = new (window.AudioContext || window.webkitAudioContext)()

function playTone(frequency, duration, volume, type, startTime) {
  const oscillator = audioCtx.createOscillator()
  const gainNode = audioCtx.createGain()
  oscillator.connect(gainNode)
  gainNode.connect(audioCtx.destination)
  oscillator.type = type
  oscillator.frequency.value = frequency
  gainNode.gain.value = volume
  oscillator.start(audioCtx.currentTime + startTime)
  oscillator.stop(audioCtx.currentTime + startTime + duration)
}

// ピンポーンという音
function play() {
  playTone(880, 0.2, 0.5, 'sine', 0)
  playTone(700, 0.4, 0.5, 'sine', 0.2)
}

play()