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クラスの一番下に書いてあるコードで一覧を出力可能です。
audioread(2015.2.11追記)
scikit.audiolabは2.7.x系でしか使えない(3系に対応したforkは存在)のですが、3.x系でも使えるライブラリとしてaudioreadというものがあります。
このライブラリはシステムにインストールされているさまざまなオーディオ関連のライブラリをバックエンドとして音声ファイルを読み込むことを可能とするライブラリで、現在は
- Gstreamer
- Core Audio(ctypes経由)
- MAD(pymadのバインディング)
- FFmpeg(コマンドラインツール)
wave
,aifc
,sunau
といったPython標準ライブラリ(非圧縮形式に対して利用)
が利用可能であるとのことです。
利点や使い方についてはこのnotebookに詳しく載っていますが、
- 良い点
- WAVEXのような形式にも対応
- WAVEXは多チャンネルに対応したWAVEの拡張フォーマット
- python2系でも3系でも利用可能
- WAVEXのような形式にも対応
- 悪い点
- たとえpcm32などの違う形式であろうと常に16bitでデータが返される
- データがバイトのチャンクとして読み出されるので、自分で配列に変換する必要がある
- チャンネル数が間違っている場合がある(1ch, 2chのファイルに対してのみ利用すべき)
- エラーやワーニングのメッセージが出ない
とのことです(最新のバージョンを追っている訳ではないので改善されているかもしれませんが)。
自分でも簡単に触ってみましたが、確かにfrombufferで16bitずつ読み出したりshortをfloatに直したりするのが面倒です。
とはいえ3系で動作するというのが大きな利点であるとは思います。
pydub(2015/5/25追記)
特に触っていませんがpydubというライブラリがあります。 サンプル単位ではなくms単位で扱うようなので厳密な計算を行いたい時には向いていないかもしれません。
pysox
これも特に触ることができていませんがlibsoxのpythonラッパーだと思われます。
Pysox audio manipulation for python documentation — pysox v0.3.5.alpha documentation
PySoundFile
audiolabのissuesのコメントでもはやメンテナンスされてないからこちらを使えと紹介されていたものです。 ぱっと見たところブロック(フレーム)単位でオーバーラップを指定して切り出せるのが便利そうです。
まとめ
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ファイルを読む方法をご存知の方は教えていただけると幸いです。