2015/07/22(水) [n年前の日記]
#1 [dxruby] SE再生処理を修正中
指定フレーム数が経過してからSEを再生できるようにしたり、ポートを指定して再生、みたいな処理を追加したり等、アレコレしていたり。
◎ 少し遅れて再生させる処理。 :
ゲームの中では、再生開始を要求してからちょっと遅れて実際の音が聞こえ始めてほしいなあ、てな場面があるのだけど。
これについては、一応、SEデータの冒頭に無音部分を入れておけば、ひとまず目的は果たせる。しかし今回、SEデータを無圧縮wavで持っているので、ファイルサイズが比較的大きくて。できれば、無音部分はできるだけ事前に削っておきたいわけで。
こんな時、「xxフレーム後に実際に再生してね」とSE再生要求ができるとありがたい。ということで、そんな感じの処理を追加。各要求にカウンタを持たせて、カウンタが0なら現在フレームで即座に鳴らしてから要求をクリア、もしカウンタが0じゃなければそのカウンタをデクリメントして要求を次のフレームにも持ち越す、みたいな感じで。
これについては、一応、SEデータの冒頭に無音部分を入れておけば、ひとまず目的は果たせる。しかし今回、SEデータを無圧縮wavで持っているので、ファイルサイズが比較的大きくて。できれば、無音部分はできるだけ事前に削っておきたいわけで。
こんな時、「xxフレーム後に実際に再生してね」とSE再生要求ができるとありがたい。ということで、そんな感じの処理を追加。各要求にカウンタを持たせて、カウンタが0なら現在フレームで即座に鳴らしてから要求をクリア、もしカウンタが0じゃなければそのカウンタをデクリメントして要求を次のフレームにも持ち越す、みたいな感じで。
◎ ポートを指定して鳴らしたい。 :
SEの種類によっては、ポートを指定して鳴らせたほうがいいものもあって。
例えばプレイヤーの音声がソレで。「はどーけん!」と必殺技を叫んでる途中で攻撃を食らって「うわっ」と叫ぶのであれば、「はどーうわっ」と聞えないとおかしいわけで。「はどー(けん!|うわっ)」と二つの音声が並列で流れてしまったら奇妙なことになるわけですよ。リュウは画面に一人しか居ないのにもう一人はどこに居るんだよ、スタンドでも居るのかよ、みたいな。
そんな時は、プレイヤーの音声はポートxx番で鳴らす、と決め打ちができるとありがたい。ポートxx番でSEを鳴らそうとした時、別のSEがそのポートで鳴ってたら、今まで鳴ってたSEの再生を停止して、それから新しいSEを鳴らす、みたいな。
ただ、そういう処理をするためには、既に鳴らしたSEは今も鳴り続けているか、それとも鳴り終わったのか、その情報を取得できないと困るわけで。残念なことに、DXRuby の Soundクラスは、既に鳴らした音声が今も鳴り続けているのか調べる機能が無いっぽい。
ということで、各SEデータが何秒のデータなのか事前に調べて YAML に記録しておいて、プログラム側はソレを使って、特定ポートで鳴らしたSEが今も鳴り続けているか・鳴り終っているかを判断するようにしてみたり。鳴らし始めてから何フレーム経ってるのかカウントしておいて、再生時間を過ぎたら鳴り終ってるし、再生時間を過ぎてなければまだ鳴ってるはずだよね、みたいな。
で。各SEデータ、つまりは wavファイルの情報を読み取って YAML にする処理も Rubyスクリプトで書いてみたり。 _wavefile という gem と、yaml というライブラリを使えば処理は書ける。 _WaveFile Gem の、Getting Metadata About a Wave File というサンプルを参考にすれば、再生時間の取得はできる。
例えばプレイヤーの音声がソレで。「はどーけん!」と必殺技を叫んでる途中で攻撃を食らって「うわっ」と叫ぶのであれば、「はどーうわっ」と聞えないとおかしいわけで。「はどー(けん!|うわっ)」と二つの音声が並列で流れてしまったら奇妙なことになるわけですよ。リュウは画面に一人しか居ないのにもう一人はどこに居るんだよ、スタンドでも居るのかよ、みたいな。
そんな時は、プレイヤーの音声はポートxx番で鳴らす、と決め打ちができるとありがたい。ポートxx番でSEを鳴らそうとした時、別のSEがそのポートで鳴ってたら、今まで鳴ってたSEの再生を停止して、それから新しいSEを鳴らす、みたいな。
ただ、そういう処理をするためには、既に鳴らしたSEは今も鳴り続けているか、それとも鳴り終わったのか、その情報を取得できないと困るわけで。残念なことに、DXRuby の Soundクラスは、既に鳴らした音声が今も鳴り続けているのか調べる機能が無いっぽい。
ということで、各SEデータが何秒のデータなのか事前に調べて YAML に記録しておいて、プログラム側はソレを使って、特定ポートで鳴らしたSEが今も鳴り続けているか・鳴り終っているかを判断するようにしてみたり。鳴らし始めてから何フレーム経ってるのかカウントしておいて、再生時間を過ぎたら鳴り終ってるし、再生時間を過ぎてなければまだ鳴ってるはずだよね、みたいな。
で。各SEデータ、つまりは wavファイルの情報を読み取って YAML にする処理も Rubyスクリプトで書いてみたり。 _wavefile という gem と、yaml というライブラリを使えば処理は書ける。 _WaveFile Gem の、Getting Metadata About a Wave File というサンプルを参考にすれば、再生時間の取得はできる。
◎ 優先順位はどうしようかな。 :
色んなSEが鳴ってる時、このSEが鳴る時はこっちのSEは鳴らないで欲しい、てな状況がありそうな気もしたり。
例えば、同フレームで、「はどーけん!」と「うわっ」の再生要求があった場合、「うわっ」は鳴らしてほしいけど「はどーけん!」は鳴らしてほしくないわけで。しかし処理の順番によっては、「うわっ」を鳴らした直後に「はどーけん!」が鳴ってしまう場合もありそうだなと。
そんな時、優先順位情報があれば便利。「うわっ」の優先順位を「はどーけん!」より高くしておくことで問題解決になる。
ちなみに、昔の家庭用ゲーム機は同時発音数が3つとか6つとかそんなもんだったので、SEの優先順位情報は必須だったのだけど。ただ、今のPC上では、その手の制限があまり無さそうなので、優先順位情報の必要性は…。
考えてみたら、そのフレームで敵の攻撃を食らってたら、必殺技を出す処理には行かずにダメージを受けた時の処理に流れていくよな。今回は優先順位の仕様を入れなくて済むかも。
余談。そういえば、ベアナックル3って、この優先順位がおかしかったせいで爽快感がすっかり無くなってしまった気がしたり。おそらくだけど、打撃音より、敵のやられ音声のほうが優先順位が高くて、敵が断末魔を上げている間、パンチやキックをしても打撃音が無くて…。アレは酷かった…。いや待てよ。そもそもアレは同時に鳴らなきゃいけないSEだったのでは。とすると、PCMとFM音源で振り分けてSEを作っておかないと…。何にせよ、SEに全くこだわりがない人達が作ってたんだろうな…。
例えば、同フレームで、「はどーけん!」と「うわっ」の再生要求があった場合、「うわっ」は鳴らしてほしいけど「はどーけん!」は鳴らしてほしくないわけで。しかし処理の順番によっては、「うわっ」を鳴らした直後に「はどーけん!」が鳴ってしまう場合もありそうだなと。
そんな時、優先順位情報があれば便利。「うわっ」の優先順位を「はどーけん!」より高くしておくことで問題解決になる。
ちなみに、昔の家庭用ゲーム機は同時発音数が3つとか6つとかそんなもんだったので、SEの優先順位情報は必須だったのだけど。ただ、今のPC上では、その手の制限があまり無さそうなので、優先順位情報の必要性は…。
考えてみたら、そのフレームで敵の攻撃を食らってたら、必殺技を出す処理には行かずにダメージを受けた時の処理に流れていくよな。今回は優先順位の仕様を入れなくて済むかも。
余談。そういえば、ベアナックル3って、この優先順位がおかしかったせいで爽快感がすっかり無くなってしまった気がしたり。おそらくだけど、打撃音より、敵のやられ音声のほうが優先順位が高くて、敵が断末魔を上げている間、パンチやキックをしても打撃音が無くて…。アレは酷かった…。いや待てよ。そもそもアレは同時に鳴らなきゃいけないSEだったのでは。とすると、PCMとFM音源で振り分けてSEを作っておかないと…。何にせよ、SEに全くこだわりがない人達が作ってたんだろうな…。
[ ツッコむ ]
以上です。