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
相关产品推荐
相关产品推荐

