You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WEB Audio API滤波器问题:滑块仅能单次调节截止频率

解决WEB Audio API滑块调节滤波器频率仅生效一次的问题

问题原因

你每次调用播放函数时都会新建一个filter实例,但滑块的事件处理函数始终引用的是第一次创建的filter对象。后续拖动滑块修改的是旧filter的参数,而当前发声的是新创建的filter,所以滑块看起来失效。


方案一:复用滤波器实例(推荐)

将滤波器的创建移到全局作用域,只初始化一次,每次播放时复用这个滤波器,这样滑块修改的始终是当前生效的滤波器参数。

JavaScript 代码

// 全局初始化音频上下文和滤波器
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let oscillator;
let gainNode;
const filter = audioCtx.createBiquadFilter();

// 初始化滤波器固定参数
filter.type = "lowpass";
filter.Q.value = 10;
filter.frequency.value = document.getElementById('filterFreq').value;

// 滑块事件监听(同时监听input和change实现实时响应)
$('#filterFreq').on('input change', function () {
  const freqValue = this.value;
  filter.frequency.value = freqValue;
  $('#filterFreqLabel').text(freqValue);
});

function playSound() {
  // 停止并清理之前的振荡器(避免冲突)
  if (oscillator) {
    oscillator.stop();
    oscillator.disconnect();
  }
  
  oscillator = audioCtx.createOscillator();
  gainNode = audioCtx.createGain();

  // 连接信号链:振荡器 -> 增益 -> 滤波器 -> 输出
  oscillator.connect(gainNode);
  gainNode.connect(filter);
  filter.connect(audioCtx.destination);

  oscillator.frequency.value = 300;
  oscillator.type = 'sawtooth';

  // 音量淡入
  gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
  gainNode.gain.linearRampToValueAtTime(0.3, audioCtx.currentTime + 0.1);

  oscillator.start(audioCtx.currentTime);
  oscillator.stop(audioCtx.currentTime + 1);

  // 播放结束后清理资源
  oscillator.onended = () => {
    oscillator.disconnect();
    gainNode.disconnect();
    oscillator = null;
    gainNode = null;
  };
}

HTML 代码(无需修改)

<input type="range" id="filterFreq" name="filterFreq" min="0" value="1000" max="20000" step="1">
<label for="filterFreq" id="filterFreqLabel">frequency</label>

方案二:跟踪当前活跃的滤波器

如果需要每次播放都新建滤波器,可以通过全局变量跟踪当前活跃的滤波器实例,确保滑块事件修改的是当前发声的滤波器。

JavaScript 代码

const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let oscillator;
let gainNode;
let currentFilter; // 存储当前活跃的滤波器

$('#filterFreq').on('input change', function () {
  const freqValue = this.value;
  $('#filterFreqLabel').text(freqValue);
  // 仅当存在活跃滤波器时修改参数
  if (currentFilter) {
    currentFilter.frequency.value = freqValue;
  }
});

function playSound() {
  if (oscillator) {
    oscillator.stop();
    oscillator.disconnect();
  }
  
  oscillator = audioCtx.createOscillator();
  gainNode = audioCtx.createGain();
  currentFilter = audioCtx.createBiquadFilter();

  // 设置当前滤波器参数
  currentFilter.type = "lowpass";
  currentFilter.Q.value = 10;
  currentFilter.frequency.value = document.getElementById('filterFreq').value;

  // 连接信号链
  oscillator.connect(gainNode);
  gainNode.connect(currentFilter);
  currentFilter.connect(audioCtx.destination);

  oscillator.frequency.value = 300;
  oscillator.type = 'sawtooth';

  gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
  gainNode.gain.linearRampToValueAtTime(0.3, audioCtx.currentTime + 0.1);

  oscillator.start(audioCtx.currentTime);
  oscillator.stop(audioCtx.currentTime + 1);

  // 播放结束后清理资源
  oscillator.onended = () => {
    oscillator.disconnect();
    gainNode.disconnect();
    currentFilter.disconnect();
    oscillator = null;
    gainNode = null;
    currentFilter = null;
  };
}

内容的提问来源于stack exchange,提问作者kkrzaevich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:50:43