Webaudio同时播放两个振荡器声音会引起震动音

Webaudio playing two oscillator sounds in a same time causes vibration sound

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

您可以看到,单击 "Play 1" 按钮对 "A" 笔记效果很好。 播放 2 按钮适用于 "C" 音符。 "Play both" 按钮同时播放时声音会很糟糕。

<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>

我猜你描述的振动是由削波引起的。当两个振荡器同时播放时,可能会分别产生 +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();

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

你肯定想降低音量。考虑平移不同的声音:减少对单个扬声器的工作可以产生更清晰的声音。

我同时使用了几十个振荡器。我制作的这个应用程序让你疯狂。这是两个振荡器的示例:

https://openmusic.gallery/play/1601

使用我上面提到的 "stereo" 概念,我使用 context.createChannelMerger,然后将每个正弦波连接到每个输出通道,效果很好。 它似乎在一对扬声器上比另一对扬声器更有效。它在 phone 上效果不佳。然而,增加增益使其在所有扬声器上都非常好,phone 我到目前为止测试过。我仍然希望有一个好的解决方案来合并这些,让它听起来像真正的空气合并。

我也只是尝试将更新后的代码粘贴到 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();