Python - 示波器
Python - Oscilloscope
我正在尝试在 python 中创建一个程序,它可以从实时音频(通过麦克风)创建一个示波器
与普通示波器的不同之处在于它只会显示一个波长,例如(所需输出):
这显示了三种不同的波长,以及它们各自在程序中的显示方式。
目前我的进度:
- 我创建了一个程序来显示图形并清除和重绘它
- 然后我创建了一个程序来实时显示声音(虽然它很慢,如果可能最好修复)
代码#1:
import matplotlib.pyplot as plt
import time
plt.ion()
#y1 is the data
y1 = [0,0.309,0.587,0.809,0.951,1,0.951,0.809,0.587,0.309,0, -0.309, -0.587, -0.809, -0.951, -1, -0.951, -0.809, -0.587, -0.309, 0]
plt.plot(y1, 'r.-') #Graph with data
plt.plot([0 for _ in y1]) #Straight line at y=0
while True:
#Update data to new data
#y1 = new data
plt.plot(y1, 'r.-') #Graph with data
plt.plot([0 for _ in y1]) #Straight line at y=0
plt.draw()
plt.pause(0.5) #Time for one wave? Need some way to find this...
plt.clf()
代码#2:
import pyaudio
import numpy as np
import matplotlib.pyplot as plt
import time
RATE = 44100
CHUNK = int(RATE/20) # RATE / number of updates per second
def soundplot(stream):
t1=time.time()
data = np.fromstring(stream.read(CHUNK),dtype=np.int16)
plt.pause(0.1) #To draw graph!
plt.clf()
plt.plot(data)
plt.draw()
plt.axis([0,len(data),-2**16/2,2**16/2])
print("took %.02f ms"%((time.time()-t1)*1000))
if __name__=="__main__":
p=pyaudio.PyAudio()
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,
frames_per_buffer=CHUNK)
for i in range(int(20*RATE/CHUNK)): #do this for 10 seconds
soundplot(stream)
stream.stop_stream()
stream.close()
p.terminate()
编辑:为了清楚起见,我想要的结果是如图所示显示一个单一波长,而不是第二个代码产生的多个波长
要显示单个波长,首先及时向前扫描,直到找到非负数据点。 (这会立即发生,第一个条目,代码 #1 中的数据。)
然后继续及时向前扫描,并在连续样本之间保持增量。最初,随着曲线接近其最大值,delta(或离散导数)将为正,然后变为负直到达到最小值,然后再次变为正。
当遇到非负数据点且delta为正时及时停止向前扫描。那时你有一个完整的波长。
编辑:
如果您有大量数据,则可以跳过一些前导数据样本。这里的关键是我们要找到一个具有正导数的零交叉点,然后继续前进,直到我们找到另一个具有正导数的零交叉点。因此,第一个决定应该既要寻找非负数据点,又要坚持正增量。
在存在噪声的情况下,我们可能会看到 delta 上的符号变化比波形周期更频繁。所以第一步可能是找到一堆样本的最小值和最大值(暗示一个范围),然后选择任意阈值,如 min + .25 * range 和 min + .75 * range,记录第一个正零交叉,等待对于超过高阈值的信号,等待它低于低阈值(在负过零之后),然后记录下一个正过零。这给了你一个波长的估计。如果您觉得有帮助,请重复估算,并采用一些方便的汇总,例如平均值或(更好的)中位数。
有了波长估计,您就可以更好地评估一对正过零似乎是 "correct" 还是由噪声引起的。拒绝比您的估计建议的距离更近的对。您可能还会发现计算平滑导数很方便,因此您不是对最后两个点的增量 (K=2) 进行计算,而是对最后 K 个点(可能是六个)进行平均。平均函数是一个拒绝高频噪声的低通滤波器。
我正在尝试在 python 中创建一个程序,它可以从实时音频(通过麦克风)创建一个示波器
与普通示波器的不同之处在于它只会显示一个波长,例如(所需输出):
这显示了三种不同的波长,以及它们各自在程序中的显示方式。
目前我的进度:
- 我创建了一个程序来显示图形并清除和重绘它
- 然后我创建了一个程序来实时显示声音(虽然它很慢,如果可能最好修复)
代码#1:
import matplotlib.pyplot as plt
import time
plt.ion()
#y1 is the data
y1 = [0,0.309,0.587,0.809,0.951,1,0.951,0.809,0.587,0.309,0, -0.309, -0.587, -0.809, -0.951, -1, -0.951, -0.809, -0.587, -0.309, 0]
plt.plot(y1, 'r.-') #Graph with data
plt.plot([0 for _ in y1]) #Straight line at y=0
while True:
#Update data to new data
#y1 = new data
plt.plot(y1, 'r.-') #Graph with data
plt.plot([0 for _ in y1]) #Straight line at y=0
plt.draw()
plt.pause(0.5) #Time for one wave? Need some way to find this...
plt.clf()
代码#2:
import pyaudio
import numpy as np
import matplotlib.pyplot as plt
import time
RATE = 44100
CHUNK = int(RATE/20) # RATE / number of updates per second
def soundplot(stream):
t1=time.time()
data = np.fromstring(stream.read(CHUNK),dtype=np.int16)
plt.pause(0.1) #To draw graph!
plt.clf()
plt.plot(data)
plt.draw()
plt.axis([0,len(data),-2**16/2,2**16/2])
print("took %.02f ms"%((time.time()-t1)*1000))
if __name__=="__main__":
p=pyaudio.PyAudio()
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,
frames_per_buffer=CHUNK)
for i in range(int(20*RATE/CHUNK)): #do this for 10 seconds
soundplot(stream)
stream.stop_stream()
stream.close()
p.terminate()
编辑:为了清楚起见,我想要的结果是如图所示显示一个单一波长,而不是第二个代码产生的多个波长
要显示单个波长,首先及时向前扫描,直到找到非负数据点。 (这会立即发生,第一个条目,代码 #1 中的数据。)
然后继续及时向前扫描,并在连续样本之间保持增量。最初,随着曲线接近其最大值,delta(或离散导数)将为正,然后变为负直到达到最小值,然后再次变为正。
当遇到非负数据点且delta为正时及时停止向前扫描。那时你有一个完整的波长。
编辑:
如果您有大量数据,则可以跳过一些前导数据样本。这里的关键是我们要找到一个具有正导数的零交叉点,然后继续前进,直到我们找到另一个具有正导数的零交叉点。因此,第一个决定应该既要寻找非负数据点,又要坚持正增量。
在存在噪声的情况下,我们可能会看到 delta 上的符号变化比波形周期更频繁。所以第一步可能是找到一堆样本的最小值和最大值(暗示一个范围),然后选择任意阈值,如 min + .25 * range 和 min + .75 * range,记录第一个正零交叉,等待对于超过高阈值的信号,等待它低于低阈值(在负过零之后),然后记录下一个正过零。这给了你一个波长的估计。如果您觉得有帮助,请重复估算,并采用一些方便的汇总,例如平均值或(更好的)中位数。
有了波长估计,您就可以更好地评估一对正过零似乎是 "correct" 还是由噪声引起的。拒绝比您的估计建议的距离更近的对。您可能还会发现计算平滑导数很方便,因此您不是对最后两个点的增量 (K=2) 进行计算,而是对最后 K 个点(可能是六个)进行平均。平均函数是一个拒绝高频噪声的低通滤波器。