【问题标题】:Python - OscilloscopePython - 示波器
【发布时间】:2019-03-07 18:57:34
【问题描述】:

我正在尝试在 python 中创建一个程序,它可以从现场音频(通过麦克风)创建一个示波器

与普通示波器的不同之处在于它只会显示一个波长,例如(期望的输出):

这显示了三种不同的波长,以及它们在程序中的显示方式。

我目前的进展:

  1. 我创建了一个程序来显示图表并清除和重绘它
  2. 然后我创建了一个可以实时显示声音的程序(虽然它很慢,如果可能的话最好修复一下)

代码 #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()

编辑:为了清楚起见,我想要的结果是如图所示显示一个波长,而不是第二个代码产生的多个波长

【问题讨论】:

  • 这很酷,但是您有问题或需要帮助吗?如果是这样,您应该更新您的帖子以包含您需要的内容。
  • 谢谢!是的,我只需要显示一个波长,如图所示,而不是同时显示多个@RandomDavis
  • @RandomDavis 我进行了编辑以使其更清晰

标签: python python-3.x audio microphone oscilloscope


【解决方案1】:

要显示单个波长,请先及时向前扫描,直到找到非负数据点。 (这将立即发生,第一个条目,代码 #1 中的数据。)

然后继续及时向前扫描,并在连续样本之间保持一个增量。最初,delta(或离散导数)将在曲线接近其最大值时为正数,然后变为负数直到达到最小值,然后再次变为正数。

遇到非负数据点且增量为正时及时停止向前扫描。那时你就有了一个完整的波长。

编辑:

如果您有大量数据,则可以跳过一些前导数据样本。这里的关键是我们要找到一个具有正导数的零交叉点,然后继续前进,直到我们找到另一个具有正导数的零交叉点。所以第一个决定应该寻找一个非负数据点并坚持正增量。

在存在噪声的情况下,我们可能会更频繁地看到 delta 上的符号变化,而不是波形的周期。所以第一步可能是找到一堆样本的最小值和最大值(暗示一个范围),然后选择任意阈值,如 min + .25 * range 和 min + .75 * range,记录第一个正过零,等待对于信号超过高阈值,等待它低于低阈值(在负过零之后),然后记录下一个正过零。这给了你一个波长的估计。如果您觉得有帮助,请重复估算,并采用一些方便的汇总,例如平均值或(更好的)中位数。

有了波长估计,您就可以更好地评估一对正过零是“正确”还是由于噪声。拒绝比您的估计更接近的对。您可能还会发现计算平滑导数很方便,因此您不是在看到最后两个点的增量 (K=2),而是对最后 K 个点进行平均,也许是六个点。平均函数是一个抑制高频噪声的低通滤波器。

【讨论】:

  • 很好的答案!有什么方法可以让我加快绘图过程,这样就不会花那么长时间,因为我必须等待大约 0.2 秒,这意味着每秒只有 5 次更新
  • 您可能对ondras.github.io/oscope 或呈现 Jerobeam Fenderson 波形的各种 Web 组装项目完成的高速绘图感兴趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
  • 2019-04-29
  • 1970-01-01
相关资源
最近更新 更多