如何使用Javascript Web Audio API修复同时播放的多个振荡器的声音

时间:2019-05-01 13:41:24

标签: javascript safari web-audio-api mobile-chrome

我正在建立一个声音装置,其中同时播放多个振荡器(在给定时间最多播放5/6个振荡器)。 它通常可以在Firefox和Chrome的桌面上运行,但是在Safari中,如果我一次播放多个振荡器,它会发出可怕的“ kkrkrkrkrkrkrkrkrkr”声音。我已经使用同一台计算机对其进行了测试,因此扬声器没有问题。在电话上,它可以在iphone上运行,但是在android上,如果使用多个浏览器,无论使用哪种浏览器,它都具有相同的“ krkrkrkr”效果。 安装的最终目标是在手机上显示,我无法控制将使用哪些浏览器

这是代码的简化版本

let audioContext;
let touchEvent = 'ontouchstart' in window ? 'touchstart' : 'click';

let oscillators = [];


window.addEventListener(touchEvent, makeSound);

function makeSound(){
    audioContext = new (window.AudioContext || window.webkitAudioContext)();

    createOsc(43.653528929125486);
    createOsc(220);
    createOsc(164.81377845643496);

    currentTime = audioContext.currentTime;
    oscillators.forEach(function(oscillator){
        currentTime = audioContext.currentTime;
        oscillator.start(currentTime);
        oscillator.stop(currentTime + 2);
    });


}

function createOsc(freq){
    oscillator = audioContext.createOscillator();
    oscillator.frequency.value = freq;
    oscillator.connect(audioContext.destination);
    oscillators.push(oscillator);
}

我已经尝试过使用ChannelMergerNode,但是它并没有改变

1 个答案:

答案 0 :(得分:0)

Chrome / Firefox和Safari在处理信号范围(从-1到+1)上的方式似乎有所不同。

如果连接所有三个振荡器,理论上信号可以达到最大值-3和+3。

如果通过添加增益约为0.333(1 /振荡器数量)的GainNode来确保信号始终保持在-1到+1范围内,则所有浏览器的声音都相同。

我更新了您的代码段以添加这样的GainNode:

let audioContext;
let gainNode;
let touchEvent = 'ontouchstart' in window ? 'touchstart' : 'click';
let oscillators = [];

window.addEventListener(touchEvent, makeSound);

function makeSound(){
    audioContext = new (window.AudioContext || window.webkitAudioContext)();

    gainNode = audioContext.createGain();

    gainNode.connect(audioContext.destination);

    createOsc(43.653528929125486);
    createOsc(220);
    createOsc(164.81377845643496);

    const currentTime = audioContext.currentTime;
    oscillators.forEach(function(oscillator){
        // The next line is probably not needed.
        // currentTime = audioContext.currentTime;
        oscillator.start(currentTime);
        oscillator.stop(currentTime + 2);
    });
}

function createOsc(freq){
    cons oscillator = audioContext.createOscillator();

    oscillator.frequency.value = freq;
    oscillator.connect(gainNode);
    oscillators.push(oscillator);

    gainNode.gain.value = 1 / oscillators.length;
}