Webaudio同时播放两个振荡器声音会导致振动声音

时间:2019-12-15 20:47:35

标签: javascript web-audio-api

使用Web Audio,我产生了声音,但听起来确实很糟糕(振动)。如果我使用非常低的增益,那就更好了,但是太安静了。与使用极低值的低通滤波器相同。在同一时间播放多个频率的正确方法是什么?

您可以看到单击“播放1”按钮可以很好地处理“ A”音符。 播放2按钮适用于“ C”音符。 当两者同时播放时,“同时播放”按钮听起来会很糟糕。

<html>
    <head>
        <title>Audio</title>
        <script>

            var context = null;
            var oscillatorNode1 = null;
            var oscillatorNode2 = null;

            function stop() {
                if ( oscillatorNode1 != null ) {
                    oscillatorNode1.stop(context.currentTime);
                    oscillatorNode1 = null;
                }
                if ( oscillatorNode2 != null ) {
                    oscillatorNode2.stop(context.currentTime);
                    oscillatorNode2 = null;
                }
            }

            function play1() {
                stop();
                if ( context === null) {
                    context = new AudioContext();
                }
                oscillatorNode1 = context.createOscillator();
                oscillatorNode1.type = 'sine';
                oscillatorNode1.frequency.value = 220;

                oscillatorNode1.connect(context.destination);
                oscillatorNode1.start();

                oscillatorNode2 = context.createOscillator();
                oscillatorNode2.type = 'sine';
                oscillatorNode2.frequency.value = 261.6255653005986;

                oscillatorNode2.connect(context.destination);
                oscillatorNode2.start();
            }

            function play2() {
                stop();
                if ( context === null) {
                    context = new AudioContext();
                }
                oscillatorNode1 = context.createOscillator();
                oscillatorNode1.type = 'sine';
                oscillatorNode1.frequency.value = 220;

                oscillatorNode1.connect(context.destination);
                oscillatorNode1.start();

            }

            function play3() {
                stop();
                if ( context === null) {
                    context = new AudioContext();
                }

                oscillatorNode2 = context.createOscillator();
                oscillatorNode2.type = 'sine';
                oscillatorNode2.frequency.value = 261.6255653005986;

                oscillatorNode2.connect(context.destination);
                oscillatorNode2.start();
            }

        </script>
    </head>
    <body>
        <form>
            <input type="button" onclick="play1()" value="Play both" />
            <input type="button" onclick="play2()" value="Play 1" />
            <input type="button" onclick="play3()" value="Play 2" />
            <input type="button" onclick="stop()" value="Stop" />
        </form>
    </body>
</html>

3 个答案:

答案 0 :(得分:0)

我猜您所描述的振动是由于削波引起的。当两个振荡器同时播放时,可能分别导致+2或-2的值。将以下代码段粘贴到Canopy的编辑器中时,您可以直观地看到它。

const osc1 = new OscillatorNode(context, { frequency: 261.6 });
const osc2 = new OscillatorNode(context, { frequency: 222 });

osc1.connect(context.destination);
osc2.connect(context.destination);

osc1.start();
osc2.start();

您可以通过添加一个值为0.5的GainNode来避免这种情况。但是,合并后的信号将被感知为更纯净的静音。这是因为纯音在+1和-1之间不断变化,而组合音并不总是达到极值。

添加GainNode之后,您的play1()函数的核心部分看起来像这样:

oscillatorNode1 = context.createOscillator();
oscillatorNode1.frequency.value = 220;

oscillatorNode2 = context.createOscillator();
oscillatorNode2.frequency.value = 261.6255653005986;

gainNode = context.createGain();
gainNode.gain.value = 0.5;

oscillatorNode1.connect(gainNode);
oscillatorNode2.connect(gainNode);
gainNode.connect(context.destination);

oscillatorNode1.start();
oscillatorNode2.start();

答案 1 :(得分:0)

这与数字音频和音频工程有很大关系。

您肯定想降低音量。考虑摇动不同的声音:减少单个扬声器的工作量可以使声音更清晰。

我实际上同时使用了数十个振荡器。我制作的这个应用程序让您疯狂。这是两个振荡器的示例:

https://openmusic.gallery/play/1601

答案 2 :(得分:0)

使用上面提到的“立体声”概念,我使用context.createChannelMerger,然后将每个正弦波连接到每个输出通道,并且效果很好。 一对扬声器似乎效果更好。在手机上效果不佳。但是,增加增益使其在到目前为止我测试过的所有扬声器和电话上都非常出色。我仍然希望在合并这些文件时有一个好的解决方案,这听起来像是真正的空中合并。

我也只是尝试将更新的代码粘贴到Canopy中,但这听起来不太好。原因之一是已经创建了音频上下文,并且创建一个新的音频上下文效果很好。因此,现有的在该Canopy页面上无法正常运行。

                context = new AudioContext();
                oscillatorNode1 = context.createOscillator();
                oscillatorNode1.type = 'sine';
                oscillatorNode1.frequency.value = 220;

                var merger = context.createChannelMerger(2);
                merger.connect(context.destination);

                oscillatorNode1.connect(merger, 0, 0);
                oscillatorNode1.start();

                oscillatorNode2 = context.createOscillator();
                oscillatorNode2.type = 'sine';
                oscillatorNode2.frequency.value = 261.6255653005986;

                oscillatorNode2.connect(merger, 0, 1);
                oscillatorNode2.start();