numpy的sin函数如何工作?

时间:2019-11-24 16:57:47

标签: python numpy scipy

几个月前,我终于想出了如何使用python程序制作声音文件。但是我有问题。该代码依赖于模块“ numpy”中名为“ sin”的函数。这是我编写的代码:

import numpy as np
from scipy.io.wavfile import write

sps=44100

freq=440.0

duration=5

amp=0.02

eachSampleNumber=np.arange(duration*sps)
waveform=np.sin(2*np.pi*eachSampleNumber*freq/sps)
waveformQuiet=waveform*amp
waveformIntegers=np.int16(waveformQuiet*32767)
write('first_sine_wave.wav',sps,waveformIntegers)

问题是,如果我做某些事情,就会发生奇怪的事情。如果更改声音的长度,则会改变音调。另外,如果我尝试将声音串联在一起(我只是通过简单地将结果数组加在一起来进行操作),那么结果声音文件将使两个声音相互重叠,而不是一个接一个地叠加。例如,如果我将两个声音相加一秒,而不是创建一个两秒钟的声音文件,两个音符一个接一个地播放,我将得到一个一秒钟的声音文件,两个音符分别为同时玩。

我不知道实际上是如何手工产生正弦波,也找不到文档向我揭示该函数使用的公式。我也不明白为什么在这种情况下将两个数组连接在一起会导致一个长度相同的数组。打印出结果数组,对我来说看起来很正常。我不明白为什么有些东西会按原样工作。

关于我如何制作声音文件,我只是在代码本身中手动更改变量并运行程序。由于我遇到的问题,我还没有做一个合适的可执行文件。我希望最终可以用它来制作自己的音乐制作者程序。

2 个答案:

答案 0 :(得分:1)

您想检查数组如何在numpy中而不是在sin函数中工作。根据{{​​3}},根据数组的形状,添加两个数组(使用+)会执行不同的操作。如果您想要一个新数组,其值来自一个值,然后是另一个值,那么您想"broadcasting" rules in numpy

我对您的代码进行了一些重新排列,以使事情变得更清晰:

import numpy as np
from scipy.io.wavfile import write

# set a global sample rate as this is fixed across one wav file
sample_rate = 44100

# define a function to return a tone at a given frequency and duration
def make_sinewave(duration, freq):
    time = np.arange(0, duration, 1/sample_rate)
    return np.sin(time * (2*np.pi*freq))

# join several tones together
waveform = np.concatenate([
    make_sinewave(1.0, 440) * 0.5,
    make_sinewave(0.5, 880) * 0.1,
    make_sinewave(0.7, 660) * 0.2,
])

# convert to appropriate data type
waveformIntegers = np.int16(waveform * 32767)

# write out
write('first_sine_wave.wav', sample_rate, waveformIntegers)

答案 1 :(得分:1)

  

如果我尝试将声音串联在一起(通过简单地将结果阵列添加在一起来完成),则结果声音文件将使两种声音彼此重叠而不是叠加在一起接another而至。

使用NumPy,数组的添加与使用Python列表的添加非常不同。前者进行元素加法,而后者进行连接。

>>> arr = np.arange(5)
>>> arr + arr
array([0, 2, 4, 6, 8])

>>> lst = list(range(5))
>>> lst + lst
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4]

要实现所需的功能,您需要使用专门的功能。

>>> np.concatenate([arr, arr], axis=0)
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4])

>>> np.hstack([arr, arr])
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4])