アナライザーで波形データと周波数スペクトルをオシロスコープのように描画する [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)
関連記事
- Waveファイルのスピード(再生速度)を変更する [WAVE.js]
- 画像の指定位置の色(RGBA)を取得する
- Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. のエラー回避方法
- Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. [Reactのエラー]
- スライダーの変更イベントの対処方法[input type="range"]
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









