(2018.2.17. 公開) (2018.8.26. 対象をバージョン 11 系列に変更)
音関係の処理は、love.audio
系の関数を使う。音ネタを読み込むのは love.audio.newSource()
。
source = love.audio.newSource(ファイル名, タイプ)
「タイプ」には "static"
か "stream"
のどちらかを指定する。"static"
は音データをすべてメモリに読み込んで処理するもの、"stream"
は必要なデータをその都度読み込んで処理するもの。(0.10.x まではタイプを省略すると "stream"
を指定したことになっていたが、11.x 以降は省略できないことになった。)
オーディオファイルのフォーマットは、拡張子で判断される。サポートされているフォーマットは次の通り(参考:LÖVE Wiki: Audio Format)。
libmodplug
がサポートするフォーマット:abc, mid, pat不勉強にして "Tracker module" フォーマット(MOD フォーマットとも)というのを知らなかったんだけど、Amiga で利用されていた種々のオーディオフォーマットの総称みたいですね。欧米で音楽・ゲームに強いコンピュータと言えば Amiga だったから、ゲームエンジンの LÖVE としては MOD フォーマットのサポートは必須なのだろう。
mid は MIDI フォーマットで、timidity を使って再生されるようだ。これが使えるのなら軽くていいじゃない、と思ったのだが、あまり実用になりそうにない。一番下にテストの結果を書いておきます。
音を鳴らすのは love.audio.play()
, 止めるのは love.audio.stop()
。
love.audio.play(source) -- 指定した音ネタを演奏する
love.audio.stop(source) -- 指定した音ネタの演奏を止める
love.audio.stop() -- すべての音ネタの演奏を止める
また、音ネタを指定する場合、次のようにも書ける。source
は、love.audio.newSource(...)
で返された値。source
の直後はピリオド .
ではなくて、コロン :
であることに注意。
source:play() -- 演奏する
source:stop() -- 止める
音ネタをループ演奏したいときは、source:setLooping()
を使う。
source:setLooping(true) -- ループ設定
source:play() -- 演奏する(無限ループ)
演奏中かどうかは source:isPlaying()
で調べられる。false
になっていれば、演奏は終了している。
if source:isPlaying() then
-- 演奏中
else
-- 演奏は終わっている
end
演奏時間、現在の演奏位置はそれぞれ source:getDuration()
, source:tell()
で調べる。演奏が終了すると、演奏位置は 0 に巻き戻される。
d = source:getDuration() -- 演奏時間
t = source:tell() -- 現在の位置
r = d - t -- 残り時間
「ある音ネタの演奏が終わったら、次の音ネタを演奏する」には、love.update()
の中で演奏の終了を調べて処理する。例えば、source1, source2, source3
を順に演奏してループするなら、こんな風になる。
function love.load()
source1 = love.audio.newSource("sound1.mp3", "static")
source2 = love.audio.newSource("sound2.mp3", "static")
source3 = love.audio.newSource("sound3.mp3", "static")
source1:play()
source0 = source1 -- 今演奏している音ネタ
end
function love.update(dt)
if not source0:isPlaying() then
-- source1 -> source2 -> source3 -> source1 ->...
if source0 == source1 then source0 = source2
elseif source0 == source2 then source0 = source3
else source0 = source1 end
source0:play()
end
end
Raspberry Pi model A+ を使って、音ネタを読み込み・演奏する時の負荷を調べてみた。使用したのは、再生時間 13 秒の mp3 ファイル。[wien.mp3] これを wien01.mp3, wien02.mp3, ...
と名前を変えて16個コピーを作り、読み込んで演奏してみる。
"static"
を指定すると、メモリ消費量(ps -o vsz
で調べたもの)が 170 MB に達した。読み込むのに要した時間は 16秒。これらを同時に演奏することは可能で、その時の %CPU は 41% 程度。
"stream"
を指定すると、メモリ消費量は 100 MB 程度になった。読み込みは 2.8 秒で完了。ところが、これらを同時に演奏しようとすると、間もなく %CPU が 100% 近くになって、音が鳴らなくなってしまう。"stream"
はデコードの負荷があるので、あまり多くの同時演奏はできないようだ。なお、8ファイルの同時演奏だと、%CPU は 66% 程度で、時々ノイズは入るが一応演奏はできた。
Windows, Mac では、64 まで同時に演奏できる。Love2D のソースの中に 64 が定数としてコーディングされているので、この値が Love2D の仕様としての上限になる。ただ、ラズパイの場合は上限値はもっと低いし、メモリ容量や CPU 負荷も考慮する必要がある。
上の mp3 の元ネタの MIDI ファイルを演奏してみた。 [wien.mid]
Mac の内蔵音源で鳴らしてみたものがこちら(先ほどの mp3 と同じ)。
(※ ウェブ版では音が再生できます)
love で鳴らすとこうなる。こりゃだめですね。音質はともかく、ノートオフがちゃんと処理されていないのが致命的。
(※ ウェブ版では音が再生できます)
ちなみに、love で mid ファイルを演奏しようとすると load_pat > can not open /usr/local/share/timidity/timidity.cfg, use environment variable MMPAT_PATH_TO_CFG for the directory
というエラーが出る。timidity.cfg
をちゃんと作って設定してやれば、あるいはまともに鳴るのかもしれない。まともに鳴ってくれるのであれば、mid ファイル+サウンドフォントの組み合わせは悪くないと思うのだが、今のところ保留にしておく。(ただ、ラズパイ上ではあまり期待はできないかも。)
目次