TOP > カテゴリ > JavaScript >

アナライザーで波形データと周波数スペクトルをオシロスコープのように描画する [Web Audio API]

Web Audio APIのAnalyserNodeで音声を解析してオシロスコープのように「波形データ」と「周波数スペクトル」をCanvasに描画します。

クラシックな曲(砂嵐)とサイン波、三角波、矩形波、のこぎり波の合計5つの音声データの波形/スペクトルをブラウザで確認する事が出来ます。

音の選択

TimeDomain
波形データ
Frequency
周波数スペクトル

波形データの縦軸は周波数、横軸は時間。周波数スペクトルの縦軸は強度、横軸は周波数です。お使いのコンピュータのサンプリング周波数が48,000の場合は周波数スペクトルの周波数は12,000Hzまで表示されます。

※砂嵐(曲)は甘茶の音楽工房さんが作成した曲を使用しています。

サイン波(正弦波)

三角波

矩形波

のこぎり波

ソースコード

波形データは信号の生データ。周波数スペクトルはAnalyserNode.getByteFrequencyData()が高速フーリエ変換(FFT)を行っています。

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<video src="waveform_spectrum_sandstorm.mp3" style="display:none;"></video>
<video src="waveform_spectrum_sine.mp3" style="display:none;"></video>
<video src="waveform_spectrum_triangle.mp3"style="display:none;"></video>
<video src="waveform_spectrum_square.mp3" style="display:none;"></video>
<video src="waveform_spectrum_sawtooth.mp3" style="display:none;"></video>
 
<p>
<button onclick="play();">再生する</button>
<button onclick="stop();">停止する</button>
</p>
<table>
  <tr>
    <th>音の選択</th>
    <td>
      <input type="radio" name="grp_option1" value="1" id="m1" checked="checked"  onchange="play();"><label for="m1">砂嵐(曲)</label> <br> 
      <input type="radio" name="grp_option1" value="2" id="m2" onchange="play();"><label for="m2">サイン波(正弦波)</label>
      <input type="radio" name="grp_option1" value="3" id="m3" onchange="play();"><label for="m3">三角波</label><br> 
      <input type="radio" name="grp_option1" value="4" id="m4" onchange="play();"><label for="m4">矩形波</label> 
      <input type="radio" name="grp_option1" value="5" id="m5" onchange="play();"><label for="m5">のこぎり波</label> 
    </td>
  </tr>
  <tr>
    <th>TimeDomain<br />波形データ</th>
    <td><canvas id="canvas1" width="256" height="255" style="border:1px solid #ccc;"></canvas></td>
  </tr>
  <tr>
    <th>Frequency<br />周波数スペクトル</th>
    <td><canvas id="canvas2" width="256" height="255" style="border:1px solid #ccc;"></canvas></td>
  </tr>
</table>
<p>波形データの縦軸は周波数、横軸は時間。周波数スペクトルの縦軸は強度、横軸は周波数です。お使いのコンピュータのサンプリング周波数が48,000の場合は周波数スペクトルの周波数は12,000Hzまで表示されます。</p>
<p>※砂嵐(曲)は<a href="http://amachamusic.chagasi.com/index.html">甘茶の音楽工房</a>さんが作成した曲を使用しています。</p>
 
<script>
var canvas1 = document.getElementById('canvas1');
var canvas2 = document.getElementById('canvas2');
var ctx1 = canvas1.getContext('2d') ;
var ctx2 = canvas2.getContext('2d') ;
 
ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);   
 
ctx1.lineWidth = ctx2.lineWidth =  1;
ctx1.strokeStyle = ctx2.strokeStyle = 'rgb(0, 0, 255)';
 
ctx1.fillStyle = ctx2.fillStyle = 'rgb(255, 255, 255)';
 
var audioCtx;
var audioSourceNode;      
var analyserNode;
var data1,data2;
 
var audioEle;
 
var firstflg = true;
 
function play(){  
   
  try{    
    if(firstflg){
      // AudioContextの生成
      audioCtx =  new AudioContext(); 
      firstflg = false;  
    }
      
    if(audioEle){
      audioEle.pause();
    }
    
    audioEle = new Audio();    
    
    if (document.getElementById("m1").checked) audioEle.src = 'waveform_spectrum_sandstorm.mp3';
    if (document.getElementById("m2").checked) audioEle.src = 'waveform_spectrum_sine.mp3';
    if (document.getElementById("m3").checked) audioEle.src = 'waveform_spectrum_triangle.mp3';
    if (document.getElementById("m4").checked) audioEle.src = 'waveform_spectrum_square.mp3';
    if (document.getElementById("m5").checked) audioEle.src = 'waveform_spectrum_sawtooth.mp3';   
    
    audioEle.autoplay = true;
    audioEle.preload = 'auto';
    
    // MediaElementAudioSourceNodeの生成
    if(audioSourceNode){
      audioSourceNode.disconnect();
    }
    audioSourceNode = audioCtx.createMediaElementSource(audioEle);
    
    // AnalyserNodeの生成 
    // ※音声の時間と周波数を解析する
    if(analyserNode){
      analyserNode.disconnect();
    }    
    analyserNode = audioCtx.createAnalyser();
    
    // FFT(高速フーリエ変換)においての周波数領域
    analyserNode.fftSize = 256;
       
    data1 = new Uint8Array(analyserNode.fftSize);
    data2 = new Uint8Array(analyserNode.fftSize / 4);
 
    // オーディオノードの設定
    audioSourceNode.connect(analyserNode);
    analyserNode.connect(audioCtx.destination);
    
    draw();  
  }catch(e){
    alert(e);
  }
} 
 
function draw() {
  requestAnimationFrame(draw);
  
  // TimeDomain(波形データ)
  analyserNode.getByteTimeDomainData(data1);  
  ctx1.fillRect(0, 0, canvas1.width, canvas1.height);
 
  ctx1.strokeStyle = 'rgb(0, 0, 255)';
  ctx1.beginPath();
  ctx1.moveTo(0, data1[0]);
  for(var i = 0; i < data1.length; i++) {
    ctx1.lineTo(i, data1[i]);
  }
  ctx1.stroke();
  
  ctx1.strokeStyle = 'rgb(255, 0, 0)';  
  ctx1.beginPath();
    ctx1.moveTo(0, 127);
    ctx1.lineTo(256, 127);
  ctx1.stroke();
  
  // Frequency(周波数スペクトル)
  analyserNode.getByteFrequencyData(data2);
  ctx2.fillRect(0, 0, canvas2.width, canvas2.height);
  
  // 周波数を簡易的に表示する
  ctx2.beginPath();
  ctx2.moveTo(0,  255 - data2[0]);
  for(var i = 0; i < data2.length; i++) {
     ctx2.lineTo(i*4, 255 - data2[i]);   
  }
  ctx2.stroke();
};
 
function stop(){  
  audioEle.pause();
}
 
</script>
</body>
</html>

このコードはあくまでも簡易的ですので、各自で拡張してください。

また、周波数スペクトルの横幅の1単位の周波数は「周波数分解能」を用います。周波数分解能はaudioCtx.sampleRate / analyserNode.fftSizeで求められます。sampleRateが48,000でfftSizeが2048の場合は48000/2048 =23.4375Hzとなります。

追記:学習用にオープンソースで波形データ&周波数スペクトルを公開したのでご参考にして下さい。

参考サイト

AnalyserNode (MDN Web Docs)
AnalyserNode.getByteFrequencyData() (MDN Web Docs)
AnalyserNode.getByteTimeDomainData() (MDN Web Docs)





関連記事



公開日:2019年02月06日 最終更新日:2019年02月12日
記事NO:02726