再见。我有一个小问题,可能部分是数学问题。在
问题是我想玩没有固定频率的正弦波。因此,为了不使声音在转换之间或在固定频率期间爆裂,我需要正弦波开始和结束振幅为零。从数学上讲,我明白该做什么。在
我选择了一种方法,我调整了正弦波的“时间”,这样它就有时间完成所有的循环。其中整数必须是整数。在
问题是,它实际上是有效的,但并不完全有效。所有的波最终都非常接近于零,但不完全在那里。改变频率的时候声音还可以,但并不完美。我搞不懂为什么最后一个元素不能落在零上。在
如果你仔细检查一下,我会非常高兴的。泰铢
import pyaudio
import numpy as np
import matplotlib.pyplot as plt
p = pyaudio.PyAudio()
volume = 0.5 # range [0.0, 1.0]
fs = 44100*4 # sampling rate, Hz, must be integer
time = 0.1 # in seconds, may be float
f = 400 # sine frequency, Hz, may be float
k = np.arange(int(time*fs))
t=np.arange(0,time,1/fs)
start=0
end=time
stream = p.open(format=pyaudio.paFloat32,
channels=1,
rate=fs,
output=True)
# generate samples, note conversion to float32 array
for i in range(1000):
start = 0
end = 40 / f #time to acomplish whole whole cycles according to the give frequency - must be whole number
print(len(t))
t = np.arange(start, end, 1 / fs)
samples = (np.sin(2*np.pi*f*t)).astype(np.float32)
print(samples[0],samples[-1]) # The main problem. I need first and last elements in the sample to be zero.
# Problem is that last element is only close to zero, which make the sound not so smooth
#print(start+i,end+i)
#print(samples) # # # # # Shows first and last element
f+=1
# for paFloat32 sample values must be in range [-1.0, 1.0]
# play. May repeat with different volume values (if done interactively)
stream.write(volume*samples)
stream.stop_stream()
stream.close()
p.terminate()
sine函数在
2*pi*N
的每一个倍数中重复自身,其中N是一个整数。低,sin(2*pi) == sin(2*pi*2) == sin(2*pi*3)
等等。在生成特定频率样本的典型方法是
sin(2*pi*i*freq/sampleRate)
,其中i
是样本号。在接下来的情况是正弦只在
i
的值处重复,这样i*freq/sampleRate
正好等于一个整数(我忽略了相位偏移)。在最终结果是,一些频率/采样器组合可能只在一个周期(1kHz@48kSr)后重复,而其他组合可能需要很长时间重复(997Hz@48kSr)。在
没有必要在精确的过零点改变频率以避免小故障。更好的方法是:
phaseInc = 2*pi*freq/sampleRate
y = sin(phase)
phase += phaseInc
如果你坚持在零交叉处改变,只需在最近的一个采样点进行,在那里相位与2*pi的倍数相交。在
相关问题 更多 >
编程相关推荐