[英]BiquadFilterNode (Web Audio API) keeps increasing its volume gradually
I have an issue with BiquadFilterNode (Web Audio API).我对 BiquadFilterNode(Web 音频 API)有疑问。 I made a simple audio program that repeats noise in every one bar.
我制作了一个简单的音频程序,在每个小节中重复噪音。 The issue is when I connect a BiquadFilterNode to the noise, its volume keeps increasing gradually.
问题是当我将 BiquadFilterNode 连接到噪声时,它的音量会逐渐增加。 Could anyone kindly point out why the gradual volume increase is happening?
谁能指出为什么会逐渐增加音量? Many thanks!
非常感谢!
Webpage running the program:运行程序的网页:
https://abirdwhale.github.io/javascript-web-audio-api-sketches/sequencers/test-biquadfilter-issue/ https://abirdwhale.github.io/javascript-web-audio-api-sketches/sequencers/test-biquadfilter-issue/
GitHub repository to recreate the issue: GitHub 存储库重新创建问题:
https://github.com/abirdwhale/javascript-web-audio-api-sketches/tree/main/sequencers/test-biquadfilter-issue https://github.com/abirdwhale/javascript-web-audio-api-sketches/tree/main/sequencers/test-biquadfilter-issue
HTML: HTML:
<!-- <!DOCTYPE html> -->
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<button id="play-button">Play/Pause</button>
<script type="module" src="js/app.js"></script>
</body>
</html>
JavaScript: JavaScript:
"use strict";
// for cross browser
const AudioContext = window.AudioContext || window.webkitaudioCtx;
const audioCtx = new AudioContext();
let futureTickTime = audioCtx.currentTime;
let counter = 1;
let tempo = 120;
let secondsPerBeat = 60 / tempo;
let counterTimeValue = (secondsPerBeat / 4); // 16th note
// Noise volume
let noiseVolume = audioCtx.createGain();
noiseVolume.gain.value = 0.001; //Noise volume before send to FX
// Noise parameters
let noiseDuration = 1.; //Duration of Noise
let bandHz = 100;
function playNoise(time, playing) {
if (playing) {
const bufferSize = audioCtx.sampleRate * noiseDuration; // set the time of the note
const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate); // create an empty buffer
const data = buffer.getChannelData(0); // get data
// fill the buffer with noise
for (let i = 0; i < bufferSize; i++) {
data[i] = Math.random() * 2 - 1;
}
// create a buffer source for our created data
const noise = audioCtx.createBufferSource();
noise.buffer = buffer;
const bandpass = audioCtx.createBiquadFilter();
bandpass.type = 'bandpass';
bandpass.frequency.value = bandHz;
// connect our graph
noise.connect(noiseVolume);
// 1. without a bandpass filter
// noiseVolume.connect(audioCtx.destination);
// 2. with a bandpass filter
noiseVolume.connect(bandpass).connect(audioCtx.destination);
if (counter === 1) {
noise.start(time);
// noise.stop(time + noiseDuration);
}
}
}
const lookahead = 25.0; // How frequently to call scheduling function (in milliseconds)
const scheduleAheadTime = 0.1; // How far ahead to schedule audio (sec)
function playTick() {
console.log("This 16th note is: " + counter);
console.log("16th is: " + counterTimeValue);
console.log("futureTickTime: " + futureTickTime);
console.log("Web Audio Time: " + audioCtx.currentTime);
counter += 1;
futureTickTime += counterTimeValue;
console.log("futureTickTime: " + futureTickTime);
if (counter > 16) {
counter = 1;
}
}
function scheduler() {
if (futureTickTime < audioCtx.currentTime + scheduleAheadTime) {
playNoise(futureTickTime, true);
playTick();
}
window.setTimeout(scheduler, lookahead);
}
scheduler();
document.getElementById("play-button").addEventListener("click", function () {
if (audioCtx.state !== "running") {
console.log("it's not running well");
audioCtx.resume();
} else {
console.log("it's running");
audioCtx.suspend();
console.log(audioCtx.state);
}
});
OK, taking BiquadFilterNode setup out of the playNoise function solved the issue.好的,从 playNoise function 中取出 BiquadFilterNode 设置解决了这个问题。 I don't understand why placing the setup inside the function was causing the issue, though.
不过,我不明白为什么将设置放在 function 中会导致问题。
Fixed JavaScript:固定 JavaScript:
"use strict";
// for cross browser
const AudioContext = window.AudioContext || window.webkitaudioCtx;
const audioCtx = new AudioContext();
let futureTickTime = audioCtx.currentTime;
let counter = 1;
let tempo = 120;
let secondsPerBeat = 60 / tempo;
let counterTimeValue = (secondsPerBeat / 4); // 16th note
// Noise volume
let noiseVolume = audioCtx.createGain();
noiseVolume.gain.value = 0.1; //Noise volume before send to FX
// Noise parameters
let noiseDuration = 1.; //Duration of Noise
let bandHz = 100;
// Biquad filter setup
const bandpass = audioCtx.createBiquadFilter();
bandpass.type = 'bandpass';
bandpass.frequency.value = bandHz;
function playNoise(time, playing) {
if (playing) {
const bufferSize = audioCtx.sampleRate * noiseDuration; // set the time of the note
const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate); // create an empty buffer
const data = buffer.getChannelData(0); // get data
// fill the buffer with noise
for (let i = 0; i < bufferSize; i++) {
data[i] = Math.random() * 2 - 1;
}
// create a buffer source for our created data
const noise = audioCtx.createBufferSource();
noise.buffer = buffer;
// connect our graph
noise.connect(noiseVolume);
// 1. without a bandpass filter
// noiseVolume.connect(audioCtx.destination);
// 2. with a bandpass filter
noiseVolume.connect(bandpass).connect(audioCtx.destination);
if (counter === 1) {
// bandpass.gain.setValueAtTime(-40, time);
noise.start(time);
// noise.stop(time + noiseDuration);
}
}
}
const lookahead = 25.0; // How frequently to call scheduling function (in milliseconds)
const scheduleAheadTime = 0.1; // How far ahead to schedule audio (sec)
function playTick() {
console.log("This 16th note is: " + counter);
console.log("16th is: " + counterTimeValue);
console.log("futureTickTime: " + futureTickTime);
console.log("Web Audio Time: " + audioCtx.currentTime);
counter += 1;
futureTickTime += counterTimeValue;
console.log("futureTickTime: " + futureTickTime);
if (counter > 16) {
counter = 1;
}
}
function scheduler() {
if (futureTickTime < audioCtx.currentTime + scheduleAheadTime) {
playNoise(futureTickTime, true);
playTick();
}
window.setTimeout(scheduler, lookahead);
}
scheduler();
document.getElementById("play-button").addEventListener("click", function () {
if (audioCtx.state !== "running") {
console.log("it's not running well");
audioCtx.resume();
} else {
console.log("it's running");
audioCtx.suspend();
console.log(audioCtx.state);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.