简体   繁体   English

BiquadFilterNode (Web Audio API) 不断增加音量

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM