顯示聲波圖形
這篇文章會使用 Python 內建的 wave 函式庫讀取的 wav 聲音檔,並透過 matplotlib 第三方函式庫,顯示聲音檔案 ( 錄音檔、mp3...等 ) 的聲波圖形。
因為程式中會使用到電腦的麥克風,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ),如果不需錄音,則可使用 Google Colab 實作,不用安裝任何軟體 ( 參考:使用 Google Colab )。
安裝 matplotlib 函式庫
輸入下列指令安裝 matplotlib 函式庫 ( 依照各人環境可使用 pip、pip3 ),相關教學可參考:matplotlib 圖表教學
!pip install matplotlib
開啟 wav 聲音檔,顯示聲波圖形
載入 matplotlib、numpy 和 wave 函式庫之後,參考下方的程式碼,執行後就能繪製出聲波圖形。
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks') # 使用 Colab 要換路徑使用
import matplotlib.pyplot as plt
import numpy as np
import wave
fig, ax = plt.subplots() # 建立單一圖表
# 建立繪製聲波的函式
def visualize(path):
raw = wave.open(path) # 開啟聲音
signal = raw.readframes(-1) # 讀取全部聲音採樣
signal = np.frombuffer(signal, dtype ="int16") # 將聲音採樣轉換成 int16 的格式所組成的 np 陣列
f_rate = raw.getframerate() # 取得 framerate
time = np.linspace(0, len(signal)/f_rate, num = len(signal)) # 根據聲音採樣產生成對應的時間
ax.plot(time, signal) # 畫線,橫軸時間,縱軸陣列值
plt.title("Sound Wave") # 圖表標題
plt.xlabel("Time") # 橫軸標題
plt.show()
visualize('oxxostudio.wav') # 讀取聲音
顯示 mp3 聲波圖形
如果要顯示 mp3 的聲波圖形,必須要先使用 pydub 函式庫,將 mp3 轉換成 wav,接著再使用同樣的方法開啟 wav,就能顯示聲波圖形。
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks') # 使用 Colab 要換路徑使用
import matplotlib.pyplot as plt
import numpy as np
import wave
from pydub import AudioSegment # 載入 pydub 的 AudioSegment 模組
song = AudioSegment.from_mp3("oxxostudio.mp3") # 讀取 mp3 檔案
song.export("oxxostudio.wav", format="wav") # 轉換並儲存為 wav
fig, ax = plt.subplots()
def visualize(path):
raw = wave.open(path)
signal = raw.readframes(-1)
signal = np.frombuffer(signal, dtype ="int16")
f_rate = raw.getframerate()
time = np.linspace(0, len(signal)/f_rate, num = len(signal))
ax.plot(time, signal)
plt.title("Sound Wave")
plt.xlabel("Time")
plt.show()
visualize('oxxostudio.wav')
顯示錄音檔案聲波圖形
參考「麥克風錄音」文章,在程式中加入繪製聲波圖形的功能,就能在錄音之後,即時顯示錄音檔案的聲波圖形 ( 先將錄音檔存成 wav,然後再讀取進行顯示 ),此外,程式裡使用了「平行任務處理」的技巧 ( 參考:輸入文字,停止函式執行 ),開始錄音之後,只要按下鍵盤的 a 就會停止錄音。
import pyaudio
import wave
from concurrent.futures import ThreadPoolExecutor
import numpy as np
import matplotlib.pyplot as plt
chunk = 1024 # 記錄聲音的樣本區塊大小
sample_format = pyaudio.paInt16 # 樣本格式,可使用 paFloat32、paInt32、paInt24、paInt16、paInt8、paUInt8、paCustomFormat
channels = 2 # 聲道數量
fs = 44100 # 取樣頻率,常見值為 44100 ( CD )、48000 ( DVD )、22050、24000、12000 和 11025。
filename = "oxxostudio.wav" # 錄音檔名
p = pyaudio.PyAudio() # 建立 pyaudio 物件
# 開啟錄音串流
stream = p.open(format=sample_format, channels=channels, rate=fs, frames_per_buffer=chunk, input=True)
frames = [] # 建立聲音串列
run = True # 設定開始錄音
fig, ax = plt.subplots() # 建立單一圖表
# 定義錄音的函式
def record():
global run, stream, p, frames, wf
print("錄音開始...")
while run:
data = stream.read(chunk)
frames.append(data) # 將聲音記錄到串列中
stream.stop_stream() # 停止錄音
stream.close() # 關閉串流
p.terminate()
print('錄音結束...')
wf = wave.open(filename, 'wb') # 開啟聲音記錄檔
wf.setnchannels(channels) # 設定聲道
wf.setsampwidth(p.get_sample_size(sample_format)) # 設定格式
wf.setframerate(fs) # 設定取樣頻率
wf.writeframes(b''.join(frames)) # 存檔
wf.close()
visualize(filename) # 執行畫圖函式
# 定義鍵盤按鍵函式
def keyin():
global run
if input() == 'a':
run = False # 如果按下 a,就上 run 等於 False
# 定義繪製圖表函式
def visualize(path):
print('畫圖...')
raw = wave.open(path) # 開啟聲音
signal = raw.readframes(-1) # 讀取全部聲音採樣
signal = np.frombuffer(signal, dtype ="int16") # 將聲音採樣轉換成 int16 的格式所組成的 np 陣列
f_rate = raw.getframerate() # 取得 framerate
time = np.linspace(0, len(signal)/f_rate, num = len(signal)) # 根據聲音採樣產生成對應的時間
ax.plot(time, signal) # 畫線,橫軸時間,縱軸陣列值
plt.title("Sound Wave") # 圖表標題
plt.xlabel("Time") # 橫軸標題
plt.show()
executor = ThreadPoolExecutor() # 平行任務處理
e2 = executor.submit(keyin)
e1 = executor.submit(record)
executor.shutdown()
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~