- 隨機信號
- 麥克風頻譜圖 <- 本文內容
- RTL-SDR頻譜圖
- FM解調
運行截圖
在上一篇中已經實現了實時顯示隨機的信號, 那麼要實現麥克風的音頻信號顯示, 待實現的就是:
- 從音頻接口讀出數據.
- 轉換數據格式, 顯示實時波形.
- 做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住程序執行, 其原因未知.