(wrist blog)

twitterはこちら http://twitter.com/wrist

pythonでwavファイルを扱う108の方法

108もないので3つ紹介します。2.7.x系でしか動作は確認してません。

2015/2/11追記: audioreadを追加

2015/5/25追記: pysox, pydub, PySoundFileを追加

wave

標準ライブラリなので何もしなくてもimport waveするだけで使えます。

import wave
    
wave_file = "/path/to/wave/file"
wf = wave.open(wave_file)
data = wf.readframes(wf.getnframes())
wf.close()

しかしこのdataを配列に読み込むなどするにはstringで返って来るために unpackしないと行けなかったりで地味にめんどくさいです。 詳しくは下記リンクを。

ドキュメントの和訳
参考:てくてくラボ

scipy.io.wavfile

scipy.ioにあるwavの読み書きクラスです。 その内良くなっていくのかもしれませんが、現状readとwriteしかなく、正直公式のwaveクラスよりも低機能な状態です。 waveを使わない場合は下記のscikits.audiolabを使った方が無難だと個人的には思ってます。

ドキュメント

scikits.audiolab

scipyよりも高度なアルゴリズムなどが実装されたscikitsですが、その中にlibsndfileのpythonラッパーであるscikits.audiolabというものが存在しています。 audiolabにはmatlabライクなwavread, wavwriteといったメソッドと、よりCのlibsndfileに近い挙動のSndfileクラスが存在しています。 以下のような感じで使います。

import scikits.audiolab as al

wave_file = "/path/to/wave/file"

# wavread
data, fs, fmt = al.wavread(wave_file)

# Sndfileクラス経由での読み込み
f = al.Sndfile(wave_file)
data = np.array(f.read_frames(f.nframes), dtype=np.float64)
f.close()

libsndfileのラッパーなのでlibsndfileで扱える形式が読み込めます。 扱える形式についてはoverviewのSndfileクラスの一番下に書いてあるコードで一覧を出力可能です。

ドキュメント
github

audioread(2015.2.11追記)

scikit.audiolabは2.7.x系でしか使えない(3系に対応したforkは存在)のですが、3.x系でも使えるライブラリとしてaudioreadというものがあります。

sampsyo/audioread · GitHub

このライブラリはシステムにインストールされているさまざまなオーディオ関連のライブラリをバックエンドとして音声ファイルを読み込むことを可能とするライブラリで、現在は

が利用可能であるとのことです。

利点や使い方についてはこのnotebookに詳しく載っていますが、

  • 良い点
    • WAVEXのような形式にも対応
      • WAVEXは多チャンネルに対応したWAVEの拡張フォーマット
    • python2系でも3系でも利用可能
  • 悪い点
    • たとえpcm32などの違う形式であろうと常に16bitでデータが返される
    • データがバイトのチャンクとして読み出されるので、自分で配列に変換する必要がある
    • チャンネル数が間違っている場合がある(1ch, 2chのファイルに対してのみ利用すべき)
    • エラーやワーニングのメッセージが出ない

とのことです(最新のバージョンを追っている訳ではないので改善されているかもしれませんが)。

自分でも簡単に触ってみましたが、確かにfrombufferで16bitずつ読み出したりshortをfloatに直したりするのが面倒です。

audioreadのテスト

とはいえ3系で動作するというのが大きな利点であるとは思います。

pydub(2015/5/25追記)

特に触っていませんがpydubというライブラリがあります。 サンプル単位ではなくms単位で扱うようなので厳密な計算を行いたい時には向いていないかもしれません。

jiaaro/pydub @ GitHub

pysox

これも特に触ることができていませんがlibsoxのpythonラッパーだと思われます。

Pysox audio manipulation for python documentation — pysox v0.3.5.alpha documentation

PySoundFile

audiolabのissuesのコメントでもはやメンテナンスされてないからこちらを使えと紹介されていたものです。 ぱっと見たところブロック(フレーム)単位でオーバーラップを指定して切り出せるのが便利そうです。

github.com

まとめ

wave, scipy.io.wavfile, scikits.audiolab, audioreadの4つを紹介しました。 個人的には量子化ビット数24bitのデータなどを読む際にwaveを使おうとしてハマった経験があるので、scikits.audiolabを推して行きたいところです。 scikits.audiolabはwindowsだとplay関数が使えないのが地味に不便だったりもするので時間があれば実装したいところです。 また、3系でも2系でも使いたいのであればaudioreadといったところでしょうか。

2015/5/25追記 audioreadよりはPySoundFIleの方が良いのではないかというissueがあります

https://github.com/cournape/audiolab/issues/28#issuecomment-104188186

またこれ以外にもwaveファイルを読む方法をご存知の方は教えていただけると幸いです。