Intro
This time, I try "BiquadFilterNode" to control tone.
Sample code
index.html
<!DOCTYPE html> <html lang="en"> <head> <title>xlsx sample</title> <meta charset="utf-8"> </head> <body> <div> <div>EQ</div> <select id="eq_input"> <option>allpass</option> <option>bandpass</option> <option>highpass</option> <option>highshelf</option> <option>lowpass</option> <option>lowshelf</option> <option>notch</option> <option>peaking</option> </select> <div>Frequency</div> <select id="eq_frequency"> <option>10</option> <option>100</option> <option>350</option> <option>1000</option> <option>5000</option> <option>10000</option> <option>22050</option> </select> <div>Gain</div> <select id="eq_gain"> <option>-40</option> <option>-20</option> <option>-10</option> <option>0</option> <option>10</option> <option>20</option> <option>40</option> </select> <div>Detune</div> <select id="eq_detune"> <option>0</option> <option>10</option> <option>100</option> <option>350</option> <option>1000</option> <option>5000</option> <option>10000</option> <option>22050</option> </select> <div>Q</div> <select id="eq_q"> <option>0</option> <option>0.0001</option> <option>0.001</option> <option>0.01</option> <option>0.1</option> <option>1</option> <option>10</option> <option>100</option> <option>1000</option> </select> </div> <script src="./js/main.page.js"></script> <script>Page.init();</script> </body> </html>
main.page.ts
let audioContext: AudioContext; export async function init(): Promise<void> { const medias = await navigator.mediaDevices.getUserMedia({ video: false, audio: true, }); audioContext = new AudioContext(); const audioSourceNode = audioContext.createMediaStreamSource(medias); const biquadFilter = audioContext.createBiquadFilter(); audioSourceNode .connect(biquadFilter) .connect(audioContext.destination); const eqSelect = document.getElementById('eq_input') as HTMLSelectElement; eqSelect.onchange = () => { const eqValue = eqSelect.options[eqSelect.selectedIndex]?.text; if(eqValue == null) { return; } switch(eqValue) { case 'allpass': biquadFilter.type = 'allpass'; break; case 'bandpass': biquadFilter.type = 'bandpass'; break; case 'highpass': biquadFilter.type = 'highpass'; break; case 'highshelf': biquadFilter.type = 'highshelf'; break; case 'lowpass': biquadFilter.type = 'lowpass'; break; case 'lowshelf': biquadFilter.type = 'lowshelf'; break; case 'notch': biquadFilter.type = 'notch'; break; case 'peaking': biquadFilter.type = 'peaking'; break; } }; const eqFrequencySelect = document.getElementById('eq_frequency') as HTMLSelectElement; eqFrequencySelect.onchange = () => { const eqFrequencyText = eqFrequencySelect.options[eqFrequencySelect.selectedIndex]?.text; if(eqFrequencyText == null) { return; } const eqFrequency = parseInt(eqFrequencyText); if(isNaN(eqFrequency)) { return; } biquadFilter.frequency.setValueAtTime(eqFrequency, audioContext.currentTime); }; const eqGainSelect = document.getElementById('eq_gain') as HTMLSelectElement; eqGainSelect.onchange = () => { const eqGainText = eqGainSelect.options[eqGainSelect.selectedIndex]?.text; if(eqGainText == null) { return; } const eqGain = parseInt(eqGainText); if(isNaN(eqGain)) { return; } biquadFilter.gain.setValueAtTime(eqGain, audioContext.currentTime); }; const eqDetuneSelect = document.getElementById('eq_detune') as HTMLSelectElement; eqDetuneSelect.onchange = () => { const eqDetuneText = eqDetuneSelect.options[eqDetuneSelect.selectedIndex]?.text; if(eqDetuneText == null) { return; } const eqDetune = parseInt(eqDetuneText); if(isNaN(eqDetune)) { return; } biquadFilter.detune.setValueAtTime(eqDetune, audioContext.currentTime); }; const eqQSelect = document.getElementById('eq_q') as HTMLSelectElement; eqQSelect.onchange = () => { const eqQText = eqQSelect.options[eqQSelect.selectedIndex]?.text; if(eqQText == null) { return; } const eqQ = parseInt(eqQText); if(isNaN(eqQ)) { return; } biquadFilter.Q.setValueAtTime(eqQ, audioContext.currentTime); }; }
type
"BiquadFilterNode" has preset filters. I can use them by "BiquadFilterNode.type".
- allpass
- bandpass
- highpass
- highshelf
- lowpass
- lowshelf
- notch
peaking
Modify filters
I can modify the selected filter by "gain", "frequency", "detune", "Q".
gain
I can control gain of filter by "BiquadFilterNode.gain".
Only "highshelf", "lowshelf", "peaking" of "BiquadFilterNode.type" can use.
The lowest value is -40(dB) and the highest one is 40(dB).
frequency, detune
"frequency", "detune" are used to compute frequency of the filter.
computedFrequency(t) = frequency(t) * pow(2, detune(t) / 1200)
- Web Audio API #BiquadFilterNode
- BiquadFilterNode.frequency - Web APIs | MDN
- BiquadFilterNode.detune - Web APIs | MDN
Because some types emphasize specific frequency by default, I can't hear the sound when I set specific values into them.
type | the value what I can't hear the sound |
---|---|
bandpass | 10 |
highpass | 22050 |
lowpass | 10 |
I can't feel the differences when I change the values with "highshelf", "lowshelf", "peaking".
Q
This express Quality factor.
I haven't understood what is Quality factor.
So maybe I will wrtite more about it later.
The max value and min value are different per types.
For example, when I use "bandpass" and set Q value as 100, I can't hear the sound.
When I use "highpass" and set Q value as 100, I hear some noize like howling.
Top comments (0)