【问题标题】:How to use the various rampToValueAtTime methods如何使用各种 rampToValueAtTime 方法
【发布时间】:2014-11-18 21:32:51
【问题描述】:

当我使用以下代码淡入文件时,它无法按预期工作。我希望在 5 秒内从 0 逐渐淡入到 1,相反,在播放文件的 5 秒内我会突然改变增益立即从 0 变为 1。我不明白什么?

soundObj.play = function() {
    playSound.buffer = soundObj.soundToPlay;
    playSound.connect(gainNode);
    gainNode.gain.value = 0;
    gainNode.gain.exponentialRampToValueAtTime(1, audioContext.currentTime + 5);
    gainNode.connect(audioContext.destination);
    playSound.start(audioContext.currentTime);
}

更新/编辑

我将上面的代码更改为以下代码,它似乎可以工作,现在我正在研究为什么。我添加了一些cmets。主要询问是否需要添加setValueAtTime方法,gain.value属性默认值是否需要非零值。

soundObj.play = function() {
    playSound.buffer = soundObj.soundToPlay;
    playSound.connect(gainNode);
    gainNode.gain.value = 0.001;  // If set to 0 it doesn't fade in
    gainNode.gain.setValueAtTime(gainNode.gain.value, audioContext.currentTime); // Is this needed to have the other RampToValue methods work ?
    gainNode.gain.exponentialRampToValueAtTime(1, audioContext.currentTime + 7);
    gainNode.connect(audioContext.destination);
    playSound.start(audioContext.currentTime);
}

【问题讨论】:

    标签: javascript asp.net-web-api html5-audio web-audio-api


    【解决方案1】:

    exponentialRampToValueAtTime 需要一个非零的正值。这不是网络音频,而是数学问题。

    真的没有办法让 0 的值呈指数增长。

    这是 Chrome 使用的算法的粗略版本(用 JS 重写):

    // start value
    var value1 = 0.1;
    // target value
    var value2 = 1;
    // start time (in seconds)
    var time1 = 0;
    // end time (in seconds)
    var time2 = 2;
    // duration
    var deltaTime = time2 - time1;
    // AudioContext sample rate
    var sampleRate = 44100;
    // total number of samples
    var numSampleFrames = deltaTime * sampleRate;
    // time incrementer
    var sampleFrameTimeIncr = 1 / sampleRate;
    // current time (in seconds)
    var currentTime = 0;
    
    // per-sample multiplier
    var multiplier = Math.pow( value2 / value1, 1 / numSampleFrames );
    // output gain values
    var values = new Array( numSampleFrames );
    
    // set up first value
    var value = value1 * Math.pow( value2 / value1, ( ( currentTime - time1 ) * sampleRate ) / numSampleFrames );
    
    for ( var i = 0; i < numSampleFrames; ++i ) {
      values[ i ] = value;
      value *= multiplier;
      currentTime += sampleFrameTimeIncr;
    }
    

    如果将value1 更改为零,您会看到输出数组基本上充满了NaN。但是 Chrome 还添加了一些额外的代码,通过特殊情况下您的值为 &lt;= 0 的情况来拯救您,这样您实际上最终不会获得 NaN 的增益值。

    如果这些都没有意义,让我这样说。为了使值呈指数增长,您基本上需要一个如下所示的循环:

    for ( var i = 0; i < length; ++i  ) {
      values[ i ] = value;
      value *= multiplier;
    }
    

    但如果你的初始值为0,那么0乘以任何其他数字总是0

    哦,如果您有兴趣(并且可以阅读 C++),这里是 Chrome 使用的代码的链接:https://chromium.googlesource.com/chromium/blink/+/master/Source/modules/webaudio/AudioParamTimeline.cpp

    相关内容在第 316 行。

    编辑

    对以 Chrome 为中心的解释表示歉意。但是,不能以指数方式增长零值的基本数学概念将适用于任何实现。

    【讨论】:

    • 谢谢,有时我太忙了以至于忘记使用常识。
    猜你喜欢
    • 1970-01-01
    • 2012-10-09
    • 2018-11-27
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多