【问题标题】:Webaudio playing two oscillator sounds in a same time causes vibration soundWebaudio同时播放两个振荡器声音会导致振动声音
【发布时间】:2019-12-15 20:47:35
【问题描述】:

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

您可以看到,单击“播放 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>

【问题讨论】:

  • 尝试在钢琴上弹奏这些音符。他们俩都很低。靠在一起的低音非常颠簸。

标签: javascript web-audio-api


【解决方案1】:

使用我上面提到的“立体声”概念,我使用 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();

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我在上面提到增加低增益会有所帮助,但不能解决问题。您的增益示例代码也没有修复它,它有帮助。添加具有非常低值的低通滤波器似乎有效,但非常安静,所以基本上它是一个非常小的增益。谢谢你的帮助。
    • 为每个振荡器创建一个增益节点。
    • @vdu 在那种情况下,我误解了这个问题。我认为您可能使用了高于 0.5 的增益值,因为您说它会产生非常无声的信号。如果低通滤波器有帮助,我猜你所说的振动只是重叠两个正弦波引起的伪影。我不确定最终是什么有助于解决这个问题。这是非常主观的。如果您想保留纯音的声音,您可以只在其他两种音调之间的频率播放一个振荡器,而不是重叠两个振荡器。
    • @MikeHelland 这两种方法听起来应该是一样的。 Web Audio API 中没有内部剪辑。至少不是只要数字保持在 JavaScript 可表示的范围内。 :-)
    • @chrisguttandin 在尝试叠加两个正弦波的效果时,我在上面的测试中打开了两个浏览器窗口。然后我在每个上播放 1 个声音,结果是一样的。我分别尝试了 Chrome 和 Firefox,结果相同。但是,当在计算机上播放 1 个声音 (Play 1) 和在我手机的免提电话上播放另一个 (Play 2) 时,将两者的音量更改为匹配,声音就可以了。通过将代码粘贴到上面的 Canopy 链接以查看我描述的内容,您可以轻松听到我描述的声音。所以现在,在我看来,计算机不像空气那样混合声音。
    【解决方案3】:

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

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

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

    https://openmusic.gallery/play/1601

    【讨论】:

    • 我不太清楚为什么需要降低音量,因为组合音量一开始并不响亮。
    • 您创建两个振荡器并播放它们,它们的音量均为 100%(默认情况下)。所以你得到 200% 的音量。将它们调低至 33%,您将听到它们而不会出现削波。
    • 确保您使用 2 个增益节点,每个振荡器一个。如果您将两个振荡器都连接到单个增益节点,然后将其调低,则信号已经削波。
    • 感谢您的建议,但降低增益没有帮助,除非它几乎听不见,这没有任何意义。两种收益或两种收益的结果相同。
    • 正弦波在低频和中频下本质上是安静的。尝试一些高音。或者尝试锯齿波。转到openmusic.gallery/gauntlet 和“添加部件”。创建任意数量的振荡器。转到“混合”面板,看看音量如何影响事物。
    猜你喜欢
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 2021-03-29
    • 2011-05-20
    相关资源
    最近更新 更多