美好的一天。我有一个小问题可能是部分数学。
事情是我想在没有固定频率的情况下播放正弦波。因此,不要在转换之间或在固定频率期间使声音破裂,我需要正弦波开始并以幅度零结束。在数学上我理解必须做什么。
我选择了一种方式,在那里我调整了正弦波的“时间”,因此它有时间完成所有周期。基本上y = sin(2 * pi f t)其中f * t必须是整数。
问题是它实际上有效但不完全。所有波浪最终都接近于零,但并非完全存在。在改变频率但不完美的情况下声音很好。我无法弄清楚为什么最后一个元素不能归零。
如果你想通过它并检查我真的很棒。 THX
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()
答案 0 :(得分:1)
正弦函数在2*pi*N
的每个倍数重复自身,其中N是整数。 IOW,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倍数的最近样本处进行。