如何使用各种rampToValueAtTime方法

How to use the various rampToValueAtTime methods

本文关键字:rampToValueAtTime 方法 何使用      更新时间:2023-09-26

当我使用以下代码淡入文件时,它无法按预期工作。我希望在 0 秒内从 5 秒逐渐淡入 1,相反,我在播放文件五秒后突然发生变化,增益立即从 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);
}

更新/编辑

我将上面的代码更改为以下内容,它似乎有效,现在我正在研究原因。我添加了一些评论。主要询问是否需要添加 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);
}

非零正值对于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还添加了一些额外的代码,通过特殊大小写实例来节省您的值<= 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 为中心的解释,我们深表歉意。但是,无法以指数方式增长零值的基本数学概念在任何实现中都成立。

相关文章:
  • 没有找到相关文章