利用Python進行錄音和音頻分析

pyaudio簡介

Python有個很強大的處理音頻的庫pyqudio, 使用pyaudio庫可以進行錄音,播放,生成wav文件等等。更多介紹可以查閱官方文檔

pyaudio安裝

各平安安裝方法 windows平臺下直接使用pip安裝即可:pip install pyqudio

錄音

import wave
import pyaudio

# 定義數據流塊
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
# 錄音時間
RECORD_SECONDS = 5
# 要寫入的文件名
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("* 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()

這裏設置的錄音時間是5秒,運行後結果如下:

recording

音頻分析

import wave
import numpy
from pyaudio import PyAudio
import matplotlib.pyplot as plt

# 只讀方式打開WAV文件
wf = wave.open('./output.wav', '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

def time_plt():
    # time也是一個數組,與wave_data[0]或wave_data[1]配對形成系列點座標
    time = numpy.arange(0, nframes)*(1.0/framerate)
    # 繪製波形圖
    plt.subplot(211)
    plt.plot(time, wave_data[0], c='r')
    plt.subplot(212)
    plt.plot(time, wave_data[1], c='g')
    plt.xlabel('time (seconds)')
    plt.show()

def freq():
    # 採樣點數,修改採樣點數和起始位置進行不同位置和長度的音頻波形分析
    N = 44100
    start = 0  # 開始採樣位置
    df = framerate/(N-1)  # 分辨率
    freq = [df*n for n in range(0, N)]  # N個元素
    wave_data2 = wave_data[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.plot(freq[:d-1], abs(c[:d-1]), 'r')
    plt.show()

def main():
    time_plt()
    freq()

if __name__ == '__main__':
    main()

代碼中的註釋比較詳細,這裏我錄了等間隔按順序唸的 “1,2,3,4”。

先讀取剛剛錄製的wav文件,頻譜分析中利用numpy包進行FFT(快速傅里葉變換)處理,最後利用matplotlib庫進行繪圖,依次繪製了波形圖和頻譜圖。

波形圖如下:

頻譜圖如下:

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