Javascript 使用Web音频API进行音量控制

Javascript 使用Web音频API进行音量控制,javascript,audio,volume,web-audio-api,Javascript,Audio,Volume,Web Audio Api,我正在做一个使用Web Audio API创建乐器的简单项目,并编写了以下代码片段(您可以按“Q”播放音符): var audio=newaudiocontext(); var体积=0; var攻击=1; var释放=1; var carrier=audio.create振荡器(); carrier.frequency.value=440.00; carrier.type=“正弦”; carrier.start(); var carrier_volume=audio.createGain();

我正在做一个使用Web Audio API创建乐器的简单项目,并编写了以下代码片段(您可以按“Q”播放音符):

var audio=newaudiocontext();
var体积=0;
var攻击=1;
var释放=1;
var carrier=audio.create振荡器();
carrier.frequency.value=440.00;
carrier.type=“正弦”;
carrier.start();
var carrier_volume=audio.createGain();
载体体积增益线性平均值时间(体积,0);
载波连接(载波与音量);
载波与音量连接(音频目的地);
文件.添加的文件列表器(“键控”,功能(e){
如果(e.keyCode==81){
载波音量增益线性平均值时间(1,audio.currentTime+攻击);
}
});
文件.附录列表(“键控”,功能(e){
如果(e.keyCode==81){
载波音量增益线性平均值时间(0,音频电流时间+释放);
}

});所以,这里是交易-LinearRamptoValueTime需要一个开始时间。当按下该键时,您打算将其设置为“现在”,但您需要通过在按下该键时设置当前值来明确它。另外,您不应该在创建时使用linearRamp-直接设置值即可

如果您直接将初始体积设置为0(via.value),它不应该完全剪切,但第一个渐变没有起点-因此它将保持为零,直到linearRamp的时间过去,然后它将跳到1

试试这个:

var audio = new AudioContext();

var volume = 0;
var attack = 1;
var release = 1;

var carrier = audio.createOscillator();
carrier.frequency.value = 440.00;
carrier.type = "sine";
carrier.start();

var carrier_volume = audio.createGain();
carrier_volume.gain.linearRampToValueAtTime(volume, 0);
carrier.connect(carrier_volume);
carrier_volume.connect(audio.destination);

// remember whether we're playing or not; otherwise the keyboard repeat will confuse us
var playing = false;

document.addEventListener("keydown", function(e) {
  if((e.keyCode == 81) && !playing) {
    // first, in case we're overlapping with a release, cancel the release ramp
    carrier_volume.gain.cancelScheduledValues(audio.currentTime);

    // now, make sure to set a "scheduling checkpoint" of the current value
    carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);

    // NOW, set the ramp
    carrier_volume.gain.linearRampToValueAtTime(1, audio.currentTime + attack);
    // Note that ideally, we would check the current value from above, and calculate 
    // the length of the attack based on it to keep a constant angle of the attack,
    // rather than a constant time.  (If we're half-way through a release when we 
    // start a new attack, the attack should only take 0.5s since we're already at 0.5.)

    playing = true;
  }
});

document.addEventListener("keyup", function(e) {
  if((e.keyCode == 81) && playing) {
    // first, in case we're overlapping with an attack, cancel the attack ramp
    carrier_volume.gain.cancelScheduledValues(audio.currentTime);

    // now, make sure to set a "scheduling checkpoint" of the current value
    carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);

    // NOW, set the ramp
    carrier_volume.gain.linearRampToValueAtTime(0, audio.currentTime + release);

    // Note that ideally, we would check the current value from above, and calculate 
    // the length of the release based on it to keep a constant angle of the release,
    // rather than a constant time.  (If we're half-way through an attack when we 
    // start a new release, the release should only take 0.5s since we're already at 0.5.)
    playing = false;
  }
});

设置音量的键

gainNode.gain.setValueAtTime(0.5,context.currentTime)

playSound
const audioPlay=async url=>{
const context=新的AudioContext();
var gainNode=context.createGain();
const source=context.createBufferSource();
const audioBuffer=等待获取(url)
.然后(res=>res.arrayBuffer())
.then(ArrayBuffer=>context.decodeAudioData(ArrayBuffer));
source.buffer=音频缓冲区;
source.connect(gainNode);
连接(context.destination);
gainNode.gain.setValueAtTime(0.5,context.currentTime);//音量,0表示静音
source.start();
};
document.querySelector(“#start”).onclick=()=>audioPlay('music/2.ogg');

非常感谢!现在听起来确实很平稳。我还将尝试一下您关于计算攻击/释放的建议。