ホーム > カテゴリ > HTML5・JavaScript >

双2次フィルタで音声の特定周波数をカット、増幅、減衰する [Web Audio API]

Web Audio APIの「双2次フィルタ」(BiquadFilterNode)を使用して音声の特定周波数をカット、増幅、減衰を行います。この双2次フィルタはマイクなどのハウリング対策にも活用可能です。

テスト用の音声は「ドレミファと伴奏」に「130Hzのサイン波」を加えてます。双2次フィルタの使用によってこの音がどうなるかを確認します。

選択 (MP3ダウンロード)

波形データ

※サイン波の生成はこちら。波形はこちらで確認できます。

フィルタ内容
ローパスフィルタ特定周波数より下を通す。それ以上は減衰する。
この例では130Hzとしています。
ハイパスフィルタ特定周波数より上を通す。それ以下は減衰する。
この例では260Hzとしています。
バンドパスフィルタ特定周波数の「範囲」を通す。それ以外は減衰。
(未使用)
ローシェルフフィルタ特定周波数より下を増幅または減衰させる。
この例では130Hzでゲインは-40としています。
ハイシェルフフィルタ特定周波数より上を増幅または減衰させる。
(未使用)
ピーキングフィルタ特定周波数の「範囲」を増幅、減衰させる。
(未使用)
ノッチフィルタ特定周波数の「範囲」を減衰させる。
この例では130Hzとしています。
オールパスフィルタ全ての周波数を通して位相関係を変える。
(未使用)
-
ローパスフィルタ + ハイパスフィルタこの例では500-800Hzを通して、それ以外は減衰しています。

※ゲインがマイナスは減衰。プラスは増幅です。
※このフィルタの使い方はBiquadFilterNode (MDN web docs)を参照。

ソースコード

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<video src="biquadfilter.mp3" style="display:none;"></video>
<p>
<button onclick="play();">再生する</button>
<button onclick="stop();">停止する</button>
</p>
<p style="color:green;;">テスト用の音声は「ドレミファと伴奏」に「130Hzのサイン波」を加えてます。双2次フィルタの使用によってこの音がどうなるかを確認します。</p>
<table>
  <tr>
    <th>選択</th>
    <td>
      <input type="radio" name="grp_option1" value="0" id="m0" checked="checked"  onchange="play();"><label for="m0">テスト用の音声</label><br>    
      <input type="radio" name="grp_option1" value="1" id="m1" onchange="play();"><label for="m1">ローパスフィルタ</label>
      <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>波形データ</th>
    <td><canvas id="canvas1" width="256" height="255" style="border:1px solid #ccc;"></canvas></td>
  </tr>
</table>
<script>
var canvas1 = document.getElementById('canvas1');
var ctx1 = canvas1.getContext('2d') ; 
ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
 
ctx1.lineWidth =  1;
ctx1.strokeStyle ='rgb(0, 0, 255)'; 
ctx1.fillStyle = 'rgb(255, 255, 255)';

var audioCtx; 
var audioSourceNode;      
var analyserNode;
var filter1,filter2;
var data1;
var bufferLength; 
 
var audioEle;

var firstflg = true;
 
function play(){  
  try{  
    
    if(firstflg){
      // AudioContextの生成
      audioCtx =  new AudioContext(); 
      firstflg = false;  
    }
    
    stop();
    
    audioEle = new Audio();        
    audioEle.src = 'biquadfilter.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;
    
    // fftSize
    bufferLength = analyserNode.fftSize;
    
    data1 = new Uint8Array(bufferLength);
 
    if(filter1){
      filter1.disconnect();
      filter1 = null;
    }       

    if(filter2){
      filter2.disconnect();
      filter2 = null;      
    }       

    // ローパスフィルタ
    if (document.getElementById("m1").checked){
      filter1 = audioCtx.createBiquadFilter();
      filter1.type='lowpass';
      filter1.frequency.value = 130; // 周波数
    }
    
    // ハイパスフィルタ
    if (document.getElementById("m2").checked){      
      filter1 = audioCtx.createBiquadFilter();
      filter1.type='highpass';
      filter1.frequency.value = 260;    
    }
    
    // ローシェルフフィルタ
    if (document.getElementById("m3").checked){
      filter1 = audioCtx.createBiquadFilter();
      filter1.type='lowshelf';
      filter1.gain.value = -40;
      filter1.frequency.value = 130; 
    }

    // ノッチフィルタ
    if (document.getElementById("m4").checked){
      filter1 = audioCtx.createBiquadFilter();
      filter1.type='notch';
      filter1.frequency.value = 130;      
    }
    
    // ローパスフィルタ + ハイパスフィルタ
    if (document.getElementById("m5").checked){
      filter1 = audioCtx.createBiquadFilter();
      filter1.type='lowpass';
      filter1.frequency.value = 800;         
      
      filter2 = audioCtx.createBiquadFilter();
      filter2.type='highpass';
      filter2.frequency.value = 500;

      // オーディオノードの設定
      audioSourceNode.connect(filter1);
      filter1.connect(filter2);
      filter2.connect(analyserNode);
      analyserNode.connect(audioCtx.destination);       
    }else{      
      // m0        
      if (document.getElementById("m0").checked){
        audioSourceNode.connect(analyserNode);
        analyserNode.connect(audioCtx.destination);  
      // m1,2,3,4  
      }else{
        audioSourceNode.connect(filter1);
        filter1.connect(analyserNode);
        analyserNode.connect(audioCtx.destination);  
      }
    }
    draw();  
  }catch(e){
    alert(e);
  }
} 
 
function draw() {
  requestAnimationFrame(draw);
  
  // 波形データ
  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 < bufferLength; 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();
};
 
function stop(){  
  if(audioEle){  
    audioEle.pause();
  }
}
 
</script>
</body>
</html>

Webアプリ

双2次フィルタ(BiquadFilter)





関連記事



公開日:2019年02月07日 最終更新日:2019年02月16日
記事NO:02727