为什么混合两个正弦听起来像一个三角形?

信息处理 声音的 音频处理 音乐 信号合成
2022-01-27 12:34:28

我不确定在哪里发布这个与通过编程进行音频合成相关的问题。

更具体地说,我正在使用一个名为synthplayer的库,它在 Python 中实现了基本的合成器。

当试图产生“和弦”效果时,即同时演奏两个音符时,我遇到了一些意想不到的事情:混合对应于音符的两个正弦波会产生三角形的声音,即不像正弦那样“圆”。

我使用下面的代码,在不知道库的情况下非常自我解释

from synthplayer.synth import WaveSynth
from synthplayer.playback import Output

synth_player = WaveSynth()


def sine(*args, **kwargs):
    return synth_player.sine(*args, **kwargs)


def get_sample():
    sine1 = sine(440, 2)
    sine2 = sine(220, 1)
    sine1.mix(sine2)
    return sine1


with Output(nchannels=1, mixing="sequential", queue_size=2) as out:
    out.play_sample(get_sample())
    out.wait_all_played()

你可以听到它:http ://sndup.net/hvz8

有没有人知道发生了什么?

3个回答

我尝试通过修改您的代码来查看您的库输出的正弦波:

def get_sample():
    sine1 = sine(440, 2)
    # sine2 = sine(220, 1)
    # sine1.mix(sine2)
    return sine1

然后绘制结果数据:

from matplotlib import pyplot as plt
def twos_comp(val, bits):
    """compute the 2's complement of int value val"""
    if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
        val = val - (1 << bits)        # compute negative value
    return val                         # return positive value as is

N = 400

int_values = [twos_comp(x,8) for x in get_sample()._Sample__frames]
plt.plot(int_values[0:N])
plt.xlim([0,N])

并得到了一些看起来不像干净的正弦波的东西:

正弦波图

我想知道图书馆是否在做正确的事情?

我对我的代码进行了修改:

plt.plot(int_values[1:N:2])

这会产生更明智的结果:

单通道图

所以它看起来像是sine()在产生一个立体声信号(或者可能是一个 16 位信号?)。

取消注释显示更多问题的sine2mix行:get_sample

在此处输入图像描述

那么也许您的代码需要在混合之前对其进行缩放?

如果我将您更改get_sample为:

def get_sample():
    sine1 = sine(440, 2, amplitude=0.4)
    sine2 = sine(220, 1, amplitude=0.4) 
    sine1.mix(sine2)
    return sine1

这会改变正弦幅度,然后我得到

这可能有效

请参阅下面的图,将两个正弦曲线加在一起,它们是谐波相关的(特别是第二个是第一个频率的两倍),但幅度和初始相位相同(在这种情况下,余弦加到余弦的两倍)频率):

添加正弦曲线

还有另一种情况,两者之间的相位不同(在这种情况下,余弦被添加到正弦中):

添加正弦曲线

这是你的耳朵和大脑在对你玩“把戏”。这只是一个(心理声学实验验证的)事实,即人耳和大脑同时准确地(或几乎准确地)将谐波相关的频率分离正弦波或正弦波分量(从同一方向,同时开始等)组合成对单一音高声音的感知;并将这些正弦泛音的数量和相对幅度组合成不同的音色感觉。