cl-libworld: 音声分析合成システムWORLDのCommon Lispラッパーを書いた
WORLDはいわゆるボコーダーというやつで、音声データから周波数スペクトルや基本周波数(F0)、非周期性指標といったパラメータを取り出したり、それらのパラメータから音声を再合成したりできる。例えばF0をいじれば音のピッチを変えられるので、歌声合成に使われたりもする(UTAUなど)。
WORLDについては作者の森勢先生のこちらのパワーポイントが分かりやすい。
WORLDはC++のライブラリなのだが、以前Common Lisp RecipesでCFFIの使い方を覚えたので、Common Lispラッパーを書いてみた。
インストール
quicklispのlocal-projects以下でgit cloneする。
cd ~/quicklisp/local-projects git clone https://github.com/masatoi/cl-libworld.git
roswellを使っている場合は以下のようにすることで~/.roswell/local-projects以下にインストールされる(git不要!)。
ros install masatoi/cl-libworld
その後Lisp処理系から読み込み。
(ql:quickload :cl-libworld)
wavファイル読み込み
まずwavファイルから音声を読み込んでWORLD-WAV構造体を作る。
(defparameter in-wav (world:make-world-wav-from-file "/path/to/vaiueo2d.wav"))
WORLD-WAV構造体の中身は、fs(フレームレート)、nbit(量子化ビット数)、data(音声データ本体)となっている。
CL-USER> (describe in-wav) #S(CL-LIBWORLD::WORLD-WAV.. [structure-object] Slots with :INSTANCE allocation: FS = 22050 NBIT = 16 DATA = #(0.001678466796875d0 0.00115966796875d0 8.23974609375d-4..
分析
次に、analysis関数で読み込んだ音声データを分析する。この関数はWORLD-PARAMS構造体を返し、この中のF0スロットに基本周波数が、spectrogramスロットにスペクトルが、aperiodicityスロットに非周期性指標がそれぞれ入っている。
(defparameter params (world:analysis in-wav))
CL-USER> (describe params) #S(CL-LIBWORLD::WORLD-PARAMS.. [structure-object] Slots with :INSTANCE allocation: FS = 22050 NBIT = 16 FRAME-PERIOD = 5.0d0 SPEED = 1 F0-FLOOR = 71.0d0 ALLOWED-RANGE = 0.1d0 Q1 = -0.15d0 F0 = #(0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0.. SPECTROGRAM = #2A((9.082863453959d-6 9.081783965827358d-6 9.078627209420748d-6.. APERIODICITY = #2A((0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0..
analysis関数にWORLDのメタパラメータを指定することができる。ほとんどはデフォルトでいいと思うが、例えばフレーム長をデフォルトの5.0msから2.0msに、F0の下限値をデフォルトの71Hzから50Hzに変えて分析するにはこのようにする。
(defparameter params2 (world:analysis in-wav :frame-period 2d0 :f0-floor 50d0))
spectrogramとaperiodicityは同じサイズ(全フレーム数×FFTサイズ)の二次元配列なのだが、フレーム長を短くしてF0の範囲を大きくしたことによりこの配列のサイズが増えてより詳細な情報を持つようになることが分かる。
CL-USER> (array-dimensions (world::world-params-spectrogram params)) (159 513) CL-USER> (array-dimensions (world::world-params-spectrogram params2)) (397 1025)
合成
analysis関数で取り出したパラメータを色々いじった後、また再合成したいときはsynthesis関数を使う。これは合成後のWORLD-WAV構造体を返す。
(defparameter out-wav (world:synthesis params))
wavファイル書き出し
output-world-wav-to-file関数でファイルに書き出せる。
(world:output-world-wav-to-file out-wav "/path/to/vaiueo2d-out.wav")