Python PyAudio,输出有点卡顿。也许是数学
Python PyAudio, output little cracky. Maybe math
美好的一天。我有一个小问题,可能部分是数学问题。
问题是我想播放没有固定频率的正弦波。因此,为了不让过渡之间或固定频率期间的声音变得刺耳,我需要正弦波以零幅度开始和结束。从数学上讲,我明白必须做什么。
我选择了一种方法,我在其中调整 'time' 正弦波,以便它有时间完成所有周期。基本上 y=sin(2*pift) 其中 f*t 必须是整数。
问题是它确实有效但并不完全。所有的波最终都非常接近于零,但不完全在那里。改变频率时声音还可以,但并不完美。我不明白为什么最后一个元素不能落在零上。
如果你能仔细检查一下,我将非常感激。感谢
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()
正弦函数在 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
正好等于一个整数(我不考虑相位偏移)。
最终结果是某些 frequency/sampleRate 组合可能仅在一个周期后重复 (1kHz @ 48kSr),而其他组合可能需要很长时间才能重复 (997Hz @ 48kSr)。
您不必为了避免毛刺而在精确的零交叉处更改频率。更好的方法是:
- 计算所需频率的相位增量为
phaseInc = 2*pi*freq/sampleRate
- 对于每个输出样本,计算当前阶段的输出样本。
y = sin(phase)
- 通过相位增量更新相位:
phase += phaseInc
- 重复 2-3 以获得所需数量的样本。
- 转到第一步更改频率
如果您坚持要在零交叉处改变,只需在最近的相位交叉 2*pi 的倍数的样本处进行。
美好的一天。我有一个小问题,可能部分是数学问题。
问题是我想播放没有固定频率的正弦波。因此,为了不让过渡之间或固定频率期间的声音变得刺耳,我需要正弦波以零幅度开始和结束。从数学上讲,我明白必须做什么。
我选择了一种方法,我在其中调整 'time' 正弦波,以便它有时间完成所有周期。基本上 y=sin(2*pift) 其中 f*t 必须是整数。
问题是它确实有效但并不完全。所有的波最终都非常接近于零,但不完全在那里。改变频率时声音还可以,但并不完美。我不明白为什么最后一个元素不能落在零上。
如果你能仔细检查一下,我将非常感激。感谢
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()
正弦函数在 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
正好等于一个整数(我不考虑相位偏移)。
最终结果是某些 frequency/sampleRate 组合可能仅在一个周期后重复 (1kHz @ 48kSr),而其他组合可能需要很长时间才能重复 (997Hz @ 48kSr)。
您不必为了避免毛刺而在精确的零交叉处更改频率。更好的方法是:
- 计算所需频率的相位增量为
phaseInc = 2*pi*freq/sampleRate
- 对于每个输出样本,计算当前阶段的输出样本。
y = sin(phase)
- 通过相位增量更新相位:
phase += phaseInc
- 重复 2-3 以获得所需数量的样本。
- 转到第一步更改频率
如果您坚持要在零交叉处改变,只需在最近的相位交叉 2*pi 的倍数的样本处进行。