在Python下實時顯示麥克風波形與頻譜

  1. 隨機信號
  2. 麥克風頻譜圖 <- 本文內容
  3. RTL-SDR頻譜圖
  4. FM解調

本文程序

運行截圖

程序運行截圖

在上一篇中已經實現了實時顯示隨機的信號, 那麼要實現麥克風的音頻信號顯示, 待實現的就是:

  1. 從音頻接口讀出數據.
  2. 轉換數據格式, 顯示實時波形.
  3. 做FFT, 顯示頻譜.

音頻接口

音頻接口用的是pyaudio, 而且是直接用的Record這個例子, 但讀取數據由調用函數讀取改爲callback讀取, 把數據放在了一個queue裏面, 這樣子寫好之後就不用管他了. 需要數據的之後直接讀取這個queue就好了.

def audio_callback(in_data, frame_count, time_info, status):
    global ad_rdy_ev

    q.put(in_data)
    ad_rdy_ev.set()
    if counter <= 0:
        return (None,pyaudio.paComplete)
    else:
        return (None,pyaudio.paContinue)

另外還包括一個event, ad_rdy_ev也就是數據OK時, 通知處理部分程序用的Event.

數據處理.

這部分我是放在一個thread裏面執行的,

def read_audio_thead(q,stream,frames,ad_rdy_ev):
    global rt_data
    global fft_data

    while stream.is_active():
        ad_rdy_ev.wait(timeout=1000)
        if not q.empty():
            #process audio data here
            data=q.get()
            while not q.empty():
                q.get()
            rt_data = np.frombuffer(data,np.dtype('<i2'))
            rt_data = rt_data * window
            fft_temp_data=fftpack.fft(rt_data,rt_data.size,overwrite_x=True)
            fft_data=np.abs(fft_temp_data)[0:fft_temp_data.size/2+1]
            if Recording :
                frames.append(data)
        ad_rdy_ev.clear()

這個線程會等待數據OK的event, 在數據OK時, 讀出一個數據, 扔掉其他的(我的機器比較慢,不扔掉我發現這個queue會越來越長). 這個數據的轉換是通過numpy的frombuffer來實現的. 後邊的 np.dtype('<i2') 的意思是little endian的16-bit整數, 參考這裏.
數據OK了, 後邊進行了處理, 這裏加了一個窗後進行fft. 對於一個numpy的array來說, 直接乘就是點乘.

顯示部分

我在顯示隨機數的那個框架(用Matplotlib顯示實時信號)上做了一些修改, 改成了顯示兩個axes, 一個是實時波形, 另一個是fft. 且fft這個圖的y軸指數的.
另外我用tkinter做了一個只有退出按鈕的小界面, 這樣可以控制程序在想退出的時候關閉.


這個程序我分別的xp環境下的cmd命令行環境和spyder中都測試了一下, OK, 但在命令行環境時, tkinter的界面會在matplotlib的窗口關掉後才彈出來. 我感覺是在matplotlib會在plt.show()時block住程序執行, 其原因未知.

原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章