WebAudio:setTargetAtTime()事件立即触发,而不是在计划的时间触发

问题描述 投票:0回答:1

我有一个Oscillator连接到Gain Node,用于创建一个音量包络,该包络<大约1.5开始后几秒钟,我想在第二个[[2:

处执行以下操作取消所有计划的(将来的)信封增益更改。
    创建新的时间表
  • setTargetAtTime
以“淡出”声音。
  • 问题是,“淡出” setTargetAtTime()似乎立即被触发,这导致了JUMP IN VOLUME。是的,如果第二个参数(startTime)小于或等于audioContext.currentTime,则可以预期。但是这里不是这种情况。

    function startSound() { //Audio context var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); var currentTime = audioCtx.currentTime; //Create Gain Node And Oscillator var gainNode = audioCtx.createGain(); var oscillator = audioCtx.createOscillator(); oscillator.type = "sine"; oscillator.frequency.setValueAtTime(440, currentTime); //Connect Oscillator to Gain Node and Gain Node to audioCtx.destination oscillator.connect(gainNode); gainNode.connect(audioCtx.destination); oscillator.start(currentTime); //Create Gain (Volume Envelope) gainNode.gain.setValueAtTime(0.5, currentTime); gainNode.gain.linearRampToValueAtTime(0.5, currentTime + 0.5); gainNode.gain.linearRampToValueAtTime(0.25, currentTime + 2); gainNode.gain.linearRampToValueAtTime(0.000001, currentTime + 5); gainNode.gain.linearRampToValueAtTime(0.000001, currentTime + 999); //Approximately 1.5 seconds later, Cancel ALL Scheduled Envelope changes from second 2 and up, and create a FAST //"Fade Out" that lasts 0.1 seconds. var cancelAt = currentTime + 2; setTimeout(function () { StopEnvelope(audioCtx, gainNode, cancelAt); }, 1500); } function StopEnvelope(audioCtx, gainNode, cancelAt) { //This is never TRUE if (cancelAt <= audioCtx.currentTime) { console.log("cancelScheduledValues will happen immediately!"); } gainNode.gain.cancelScheduledValues(cancelAt); gainNode.gain.setTargetAtTime(0.00001, cancelAt, 0.1); }
    <input type="button" value="Start Oscillator" onclick="startSound();" /> <p> You can hear a JUMP in Gain (Volume) at around 1.5 seconds. That is when <strong>gainNode.gain.setTargetAtTime(0.00001, cancelAt, 0.1);</strong> is executed. It's is like it is executed Immedately instead at cancelAt (at second 2). </p> <p style="color: red; font-weight: bold;"> NOTE: this would be expected if cancelAt <= audioCtx.currentTime. But that is NOT the case here. </p>
    非常奇怪的是,如果我将一点时间添加到预定的事件中,它的行为似乎与预期的一样。参见行[[cancelAt + = 0.0005;
     

    function startSound() { //Audio context var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); var currentTime = audioCtx.currentTime; //Create Gain Node And Oscillator var gainNode = audioCtx.createGain(); var oscillator = audioCtx.createOscillator(); oscillator.type = "sine"; oscillator.frequency.setValueAtTime(440, currentTime); //Connect Oscillator to Gain Node and Gain Node to audioCtx.destination oscillator.connect(gainNode); gainNode.connect(audioCtx.destination); oscillator.start(currentTime); //Create Gain (Volume Envelope) gainNode.gain.setValueAtTime(0.5, currentTime); gainNode.gain.linearRampToValueAtTime(0.5, currentTime + 0.5); gainNode.gain.linearRampToValueAtTime(0.25, currentTime + 2); gainNode.gain.linearRampToValueAtTime(0.000001, currentTime + 5); gainNode.gain.linearRampToValueAtTime(0.000001, currentTime + 999); //Approximately 1.5 seconds later, Cancel ALL Scheduled Envelope changes from second 2 and up, and create a FAST //"Fade Out" that lasts 0.1 seconds. var cancelAt = currentTime + 2; setTimeout(function () { StopEnvelope(audioCtx, gainNode, cancelAt); }, 1500); } function StopEnvelope(audioCtx, gainNode, cancelAt) { cancelAt += 0.0005; //This is never TRUE if (cancelAt <= audioCtx.currentTime) { console.log("cancelScheduledValues will happen immediately!"); } gainNode.gain.cancelScheduledValues(cancelAt); gainNode.gain.setTargetAtTime(0.00001, cancelAt, 0.1); }

    <input type="button" value="Start Oscillator" onclick="startSound();" /> <p> Now the "Fade Out" works as expected. The only change is that 0.0005 seconds is added to the <strong>cancelAt</strong> paramenter. </p> <p style="color: red; font-weight: bold;"> NOTE: As before, cancelAt is NEVER less than or equal to audioCtx.currentTime. </p>
  • javascript html5-audio webaudio
    1个回答
    0
    投票
    您可以使用cancelScheduledValues()而不是cancelAndHoldAtTime()来实现所需的行为。它会保留上一个值,下一个自动化将从此处开始。
    © www.soinside.com 2019 - 2024. All rights reserved.