##matlab轉python實作(四)
##后附完整代碼及windows環境下的pyaudio庫的安裝,
Wav信號的錄制與頻譜分析
程式結構
自定義函式
#定義sound recoding 函式
引數為錄音時間t,
def sound_rec(t):
#定義wav檔案讀取函式
引數為wav檔案的路徑path,代碼中因為保存的錄音檔案就在該代碼路徑下,可以不用輸入絕對路徑,回傳值為:左右聲道的波形陣列wave_data,采樣率framerate,采樣率*時間nframes
def wave_read(path):
#定義畫出時域上的波形圖函式time plot
第一個引數為采樣率,第二個引數為采樣率*時間,第三個引數為左右聲道的資料wave data list
def time_plt(frames,nframes,wave):
#定義畫出信號頻譜上的波形圖函式frequence plot
第一個引數為采樣率,第二個引數為左右聲道的資料wave data list
def freq_plt(frames,wave):
主要行程
a.
錄制音頻,將音頻保存在檔案路徑下的output.wav檔案中,(本步驟可以忽略,在已經錄制過音頻的情況下,)
b.
讀取音頻信號,將雙聲道信號的資訊存盤在陣列中,并得出采樣率,以及信號長度,
c.
做出時域上的波形圖,頻域上,進行傅里葉變換,單邊譜處理以及歸一化處理,得出頻域幅度譜,最后一起顯示,
附完整代碼
import wave
import pyaudio
import numpy
from pyaudio import PyAudio
import matplotlib.pyplot as plt
#定義sound recoding 函式,其引數為錄音時間t
def sound_rec(t):
# 定義資料流塊
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
# 錄音時間
RECORD_SECONDS = t
# 要寫入的檔案名
WAVE_OUTPUT_FILENAME = "output.wav"
# 創建PyAudio物件
p = pyaudio.PyAudio()
# 打開資料流
stream = p.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,frames_per_buffer=CHUNK)
print("start recording")
# 開始錄音
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("done recording")
# 停止資料流
stream.stop_stream()
stream.close()
# 關閉PyAudio
p.terminate()
# 寫入錄音檔案
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
#定義wav檔案讀取函式,其引數為wav檔案的路徑path
#回傳值為:左右聲道的波形陣列wave_data,采樣率framerate,采樣率*時間nframes
def wave_read(path):
wf = wave.open(path, 'rb')
# 創建PyAudio物件
p = PyAudio()
stream = p.open(format = p.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True)
nframes = wf.getnframes()
framerate = wf.getframerate()
# 讀取完整的幀資料到str_data中,這是一個string型別的資料
str_data = wf.readframes(nframes)
wf.close()
# 將波形資料轉換成陣列
wave_data = numpy.fromstring(str_data, dtype=numpy.short)
# 將wave_data陣列改為2列,行數自動匹配
wave_data.shape = -1,2
# 將陣列轉置
wave_data = wave_data.T
return wave_data,framerate,nframes
#定義畫出時域上的波形圖函式time plot
#第一個引數為采樣率,第二個引數為采樣率*時間,第三個引數為左右聲道的資料wave data list
def time_plt(frames,nframes,wave):
# time也是一個陣列,與wave_data[0]或wave_data[1]配對形成系列點坐標
time = numpy.arange(0, nframes)*(1.0/frames)
# 繪制波形圖
plt.figure(num=1,figsize=(6,4))
plt.subplot(211)
plt.plot(time, wave[0], c='r')
plt.subplot(212)
plt.plot(time, wave[1], c='g')
plt.xlabel('time (seconds)')
plt.ylabel('ampliude')
#定義畫出信號頻域上的波形函式frequence plot
#第一個引數為采樣率,第二個引數為左右聲道的資料wave data list
def freq_plt(frames,wave):
# 采樣點數,修改采樣點數和起始位置進行不同位置和長度的音頻波形分析
N = 44100
start = 0 # 開始采樣位置
df = frames/(N-1) # 解析度
freq = [df*n for n in range(0, N)] # N個元素
wave_data2 = wave[0][start:start+N]
c = numpy.fft.fft(wave_data2)*2/N
# 常規顯示采樣頻率一半的頻譜
d = int(len(c)/2)
# 僅顯示頻率在4000以下的頻譜
while freq[d] > 4000:
d -= 10
plt.figure(num=2,figsize=(6,4))
plt.plot(freq[:d-1], abs(c[:d-1]), 'r')
#sound_rec(5)
wave,frames,nframes=wave_read('output.wav')
time_plt(frames,nframes,wave)
freq_plt(frames,wave)
plt.show()
windows下安裝pyaudio庫
建議工具:一個python編輯器(用來查看你的python.exe存放的位置),windows powershell,
首先下載一個
直接使用pip install來安裝會報錯error:failed building wheel for pyaudio,
找適合自己的版本,本機環境為window+python3.7選擇了PyAudio-0.2.11-cp37-cp37m-win_amd64.whl,自己看情況選擇,
下載完后放在自己的python的Scripts檔案夾下;這里找不到可以在自己的python編輯器里面找路徑,會方便一點,
之后通過powershell進入scripts檔案夾下:
~$: cd Scripts
~/Scripts$: pip install PyAudio-0.2.11-cp37-cp37m-win_amd64.whl
~/Scripts$: pip install pyaudio
最后試用上述代碼,沒報錯就為成功,