社会人研究者が色々頑張るブログ

pythonで画像処理やパターン認識をやっていきます

pythonで音声ファイルの読み込み

やりたいこと

pythonで音声ファイル(mp3, wav)を読み込み、時系列情報(numpy array)にしたい。

ライブラリ

音声ファイルを読み込むライブラリは幾つかあるみたいです。

ライブラリ名 特長 インストール法
wave wavのみ対応 標準ライブラリ
pydub ffmpegと連携し様々なフォーマットを扱える pydub
spAudio spPluginと連携し様々なフォーマットを扱える spplugin

ざっと調べた感じでは、信号処理や再生等を他のライブラリに任せてしまえば、ライブラリ間の差はあまり無さそうに感じます。
今回は、情報が多そうなpydubを使っていこうと思います。

pydubのインストール

pipを使う場合は公式ドキュメントに従い、ターミナルに次のように入力します。

pip install pydub

condaを用いる場合は、conda-forgeリポジトリを参照します。

conda install -c conda-forge pydub

とても簡単ですね。

音声ファイルの入出力

音声ファイルの読み込みは次のように記述します。

from pydub import AudioSegment

song = AudioSegment.from_wav("test.wav")

print(song.duration_seconds) # 再生時間
print(song.frame_rate) # サンプリングレート
print(song.channels) # チャンネル数

これを実行すると次のようになりました。

9.5
44100
2

サンプリングレートが44.1KHzで9.5秒録音された、L/Rのステレオ音源であることがわかりますね。

numpy arrayへの変換は次のようになります。

song_array = np.array(song.get_array_of_samples())
print(song.array.dtype) # データ型
print(song_array.size)  # 信号長

これを実行すると

dtype('int16')
837900

となります。 この音源はサンプリングレート44.1KHz、チャンネル数2、録音時間9.5秒なので、44100×2×9.5=837900でぴったりですね。
また、チャンネルデータの保存形式は次のようになります。

f:id:nsr_9:20210921105943p:plain

ch1, ch2が交互に記録されています。
numpyのスライス機能を使えば片方のチャンネルを簡単に取り出せます。

array_ch1 = song_array[::2]
array_ch2 = song_array[1::2]

編集後のnumpy arrayからaudioファイルを書き出す際は次のように、AudioSegmentインスタンスを生成します。

song2 = AudioSegment(
    data = song_array.astype("int16").tobytes(),
    sample_width=song.sample_width, # 2byte (16bit)
    frame_rate=song.frame_rate, # 44100hz
    channels=song.channels, # stereo 2ch
)

song2.export("song.wav", format="wav")
    

これでsong.wavファイルが生成されます。
次回は読み込んだ音声データを使って色々信号処理をやっていこうと思います。