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

与普通示波器的区别在于,该示波器仅显示一个波长,例如(所需输出):

python - Python-示波器-LMLPHP

这显示了三个不同的波长,以及它们如何分别显示在程序中。

到目前为止,我的进度:

  • 我创建了一个程序来显示图形并清除并重绘它
  • 然后,我创建了一个程序,它将实时显示声音(尽管它非常慢,如果可能的话,最好将其修复)

  • 代码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时立即发生。)

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

    当遇到非负数据点并且增量为正时,请及时停止向前扫描。此时,您拥有一个完整的波长。

    编辑:

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

    在存在噪声的情况下,我们可能会看到符号变化比波形周期更频繁。因此,第一步可能是找到一堆样本的最小值和最大值(暗含一个范围),然后选择任意阈值,例如min + .25 * range和min + .75 * range,记录第一个正零交叉点,等待要使信号超过高阈值,请等待其低于低阈值(在负零交叉之后),然后记录下一个正零交叉。这样可以估算波长。如果发现有帮助,请进行重复估算,并取一些方便的汇总,例如均值或(更好)中位数。

    有了波长估计,您可以更好地评估一对正零交叉点看起来是“正确”还是由于噪声。拒绝对的距离比您的估计要紧密得多。您可能还会发现计算平滑的导数很方便,因此,您要对最近的K个点(可能是其中的六个)进行平均,而不是最后看到的两个点的增量(K = 2)。平均功能是一个低通滤波器,可抑制高频噪声。

    07-28 05:55