Rubyで大きなwavファイルを読む (未完)

訳あってwaveファイルの処理をする必要があったのでRubyを使ってやってみた。やりたいのはwavファイルをNumo::NArrayの形式で読むこと。また、使用したsample.wavはかなり大きい(2時間分、約1.2GB)。

ruby wave file」あたりでググるとだいたい以下の2つのgemが出てくる。

両方を試してみたが、結論から言うとどちらも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*")