訳あってwaveファイルの処理をする必要があったのでRubyを使ってやってみた。やりたいのはwavファイルをNumo::NArrayの形式で読むこと。また、使用したsample.wavはかなり大きい(2時間分、約1.2GB)。
「ruby wave file」あたりでググるとだいたい以下の2つのgemが出てくる。
- jstrait/wavefile:
gem install wavefile
- shokai/ruby-wav-file:
gem instlal wav-file
両方を試してみたが、結論から言うとどちらもPythonに比べてかなり時間がかかるため結構つらい。以下詳細。
参考: Pythonの場合
本題のRubyの前に、PythonでwavファイルをNumPyのndarrayで読むには以下のようにする。動作も速く、1.0~1.5秒ほど。
最後にsum()
で合計を求めているのは何らかの遅延評価的なもの(読み込んだように見えて実際には読んでおらず、必要になったときにはじめて読む)がないことを確認するため。
#!/usr/bin/env python import wave import numpy as np with wave.open("sample.wav") as wf: nframes = wf.getnframes() frames = wf.readframes(nframes) data = np.frombuffer(frames, dtype=np.int16) print(np.sum(data))
wavefileの場合
wavファイルを読むコードはだいたい以下のようになる。each_buffer
の中身が空なのでファイルを読むだけで何もしていない。これだけでも1分7秒かかった。NArrayに変換するとさらに時間がかかるだろう。
#!/usr/bin/env ruby require "wavefile" WaveFile::Reader.new("sample.wav"){|wr| wr.each_buffer{|buf| } }
wav-fileの場合
こちらのgemの場合は以下のようになる。readDataChunk()
までなら約1秒ほどだが、バイナリデータを取得するためにunpack()
まで行うと約30秒かかる。
#!/usr/bin/env ruby require "wav-file" f = open("sample.wav") format = WavFile::readFormat(f) dataChunk = WavFile::readDataChunk(f) f.close wavs = dataChunk.data.unpack("s*")