2013年11月6日

Go 言語でオーディオリサンプリングなど

前回の記事では DirectSound を Go 言語から直接叩けるようにした。
今回は Wave ファイルの読み書き、サンプルフォーマット変換、リサンプリングしてみた。

簡単なデモを用意してみた。

こんなファイルを

こんな感じに加工できます。

以下、ライブラリに関する説明など。

https://github.com/oov/audio

http://godoc.org/github.com/oov/audio
http://godoc.org/github.com/oov/audio/converter
http://godoc.org/github.com/oov/audio/resampler
http://godoc.org/github.com/oov/audio/wave

audio には audio.Readeraudio.Writer などのインターフェイスがあって、どんなオーディオフォーマットであっても float64 または float32 で扱えるようなインターフェイスにしてある。
Interleaved が付くものはチャンネルが複数あるオーディオデータで1サンプルずつ全チャンネルのデータが並んでいる形式のもの。

converter にはオーディオフォーマット変換処理がだらだらと書かれているものの、基本的には converter.Converterconverter.InterleavedConverter インターフェイスを実装している converter.Int16 などを使うと、任意のフォーマットで格納された []byte から []float32 / []float64 への変換がスムーズに行えるようになっている。
変換元のデータが既に []int16 など特定の型になっている場合は converter.Int16ToFloat64Slice などを直接使うこともできる。

resamplerOpus-tools に含まれる resample.c を Go 言語に移植したもの。
Cgo は使っていないし unsafe なコードとかもないのでどこでも動くと思うけど、その分速度は犠牲になっていると思う。元のコードにある ARM 用のアセンブリコードとか固定小数点版のコードとかは移植しておらず、リサンプリング中のレート変更なども現段階では非対応。

wave は無圧縮の *.wav を読み書きするためのライブラリ。
フォーマット情報に関しては wave.WaveFormatExtensible を渡しあう形になってるけど、WaveFormatEx の ExtSize を 0 にした場合はただの WaveFormat として振る舞う。
読み書きに対応しているサンプリングフォーマットは 8bit, 16bit, 24bit, 32bit, 32bit float, 64bit float で、Broadcast Wave Format とかの存在は考慮してない。

これらのライブラリを使ったサンプルとして resample.go を用意した。
Mac や Linux などでは
$ go run $GOPATH/src/github.com/oov/audio/resample.go hogehoge.wav
Windows では
> go run %GOPATH%\src\github.com\oov\audio\resample.go hogehoge.wav
などとすると、hogehoge.wav.out.wav というファイル名でリサンプリングされてピッチが変わったファイルが生成される。生成したものを mp3 に変換したのが上の方に貼ったやつ。
Clip to Evernote