おことわり
一体いつの時代の話してるんだよ? という感じの日記です.
話
Win32API で作ってるゲームにちょいと BGM をつけようと思い,SendMCICommand()
を使ってた大昔のコードを引っ張り出してきて再利用した.
で,まぁ音は出るっちゃ出るんだが, 出るまで数秒(2~3秒くらい?)の遅延が発生する .
ゲームの場面が切り替わるたびに数秒の無音時間が発生するという残念無念な有様となったのである.
MCI って,なにやら どっかの時点(WinXP? Win7?)で遅延が大きくなって,そのあたりの時代でコレを使ってたフリーゲームとかがわりと残念なことになっていた記憶があったので,「ひどい有様なのは MCI だから仕方ないね」とか脳死で思ってたんだけど,ちゃんと調べてみると,実は自分の使い方に結構な問題があったという話.
遅延の原因
引っ張り出してきて中身もろくに検めずに使っていたコードを確認してみると,BGMを切り替える処理が毎回
- 現在のBGMの再生を止める:
MCI_STOP
- 現在のBGMデータを捨てる(?):
MCI_CLOSE
- 新しいBGMファイルを開く:
MCI_OPEN
- 開いたBGMを再生:
MCI_PLAY
というのをやっていた.
要は,単一のBGMデータのみを管理している形の実装になっていて,毎回実施される MCI_OPEN
が数秒要していたのである.
つまり,「再生」に時間がかかってたわけじゃないのだ.
改善
これ,よくよくリファレンス読んでみると,普通に複数個のBGMファイルを MCI_OPEN
しておける んじゃん! っていう.
MCI_OPEN
する毎にちゃんと異なる MCIDEVICEID
値を返してくれることになってる.
なので,
- いちいち既存を
MCI_CLOSE
しない:
MCI_OPEN
したやつは最後(APP終了時あたり)でまとめてMCI_CLOSE
すればよい
という形にして,BGM切替はふつーに
- 現在のBGMを止める
MCI_STOP
- 再生したいBGMを再生
MCI_PLAY
で済むのね.
(切り替えた際に先頭から再生して欲しいなら MCI_SEEK
も必要だが)
これでBGMの切り替わり具合がかなりマシになった.よかった.
あとは,そしたら MCI_OPEN
はいつやるか? という話があるが,それは「そのBGMを初めて鳴らすタイミングでやる」とかでもいいかな,と.
これだと当然,ゲーム中に突然2~3秒ほど遅延が発生する形にはなるのだが,「BGM切替毎に毎回」が「BGMごとに1回だけ」に大きく改善されたわけで,許容範囲かなー,と.
(「APP起動時あたりに全BGM分をまとめてやる」とかだと起動に時間かかることになるだろうし,使わん物まで毎回読み込むというのも何か嫌だし.)
関係ない話
効果音の方は PlaySound()
を使っているのだけど,なんかこいつ,Win11になってから遅延が発生するようになった?
しかも遅延具合が一定ではなく 0~1.5 秒くらいでランダムな雰囲気だ.何これ?
PlaySound()
は ちょっと前にミニゲーム作ったとき にも使っていて,その時は別PCでWin11じゃなかったのだが,音の再生が遅れるなんてことはなかった.
そのミニゲームを今使っている Win11 な PC に持ってきてみると,やはり音が遅れるのである.
こいつに関しては対処方法が謎.