こんにちは。
私は2~3ヶ程月前に貴HPを発見し、C言語の勉強を始めました。とてもわかりやすく解説されているのでとてもありがたく活用させていただいております。
私もゲームを作りたいと思い、今少しずつプログラムを組んでいるのですが、BGMを鳴らすところでいきずづまっ
てしまいました。
始めは容量の少ない「midi」の音楽を鳴らそうと思い、「PlayMusic」関数を使って曲を流してみました。
しかし、次の曲に切り替えようとすると、明らかに判るくらい間が空いてしまいました。
そこで、曲を「ogg」にしてメモリに読み込ませて再生したら綺麗に音がつながりました。
しかし、「ogg」や「mp3」のような圧縮されたデータは、メモリ上にどのように格納されているのでしょうか?曲の長さにもよるのでしょうが、展開された状態で入るのでしょうか?
もしそうだとすると、あまりたくさんの曲データをいれてしまうととんでもないことになるので、対処法を考えない
といけません。皆さんがゲームを作るときはどのようにされているのでしょうか?
是非アドバイスください。宜しくお願いします。
BGMについて
Re:BGMについて
>「ogg」や「mp3」のような圧縮されたデータは、メモリ上にどのように格納されているのでしょうか?
これは Dxライブラリの話と考えていいのでしょうか?
仮にそうだとして、 PlayMusic()/PlaySound()関数の mp3/oggなどの再生は
内部で指定したファイルを丸ごとメモリに読み込んで、それから再生を始めます。
再生処理そのものは DirectSoundで行っており、多分ですが再生している
ところより少し先を mp3/oggから生の wavに変換して順次再生しているはずです。
なので、mp3/oggファイルそのものはメモリに展開されていますが、
直で再生可能なナマの wavへの展開は再生に必要な部分だけとなります。
>もしそうだとすると、あまりたくさんの曲データをいれてしまうと
>とんでもないことになるので
ハードディスクの方はたくさん曲があると大変なことになるかもしれませんが、
PlayMusic()/PlaySound()に限って言えば、同時に1曲しか再生できない仕様になっていて、
その制限から、過去に再生していたデータはメモリ上から消していますので、
メモリ的には1曲分しか消費しません。
なので、1曲が数十MB以上あるとかじゃない限り、そうそう心配はないかと思います。
(PlayMusic()ではなく、PlaySoundMem()などの自分でサウンドの状態を管理する場合は
勝手にメモリから消えたりはしないので注意が必要です。)
>皆さんがゲームを作るときはどのようにされているのでしょうか?
Dxライブラリはほとんどまともに使ったことがないので、参考になるかどうかわかりませんが。
Midiにするか mp3にするかは音質とゲームの総容量と相談ですね。
メモリに対する基本戦略はとりあえず本当に必要になるまで読み込まないか、
問答無用で全部最初に読み込んでおく、のどちらかになるかと思います。
どちらも一長一短ですが、個人的には無駄なメモリを喰わない&後から
「メモリ食い過ぎ!」状態になって後悔する可能性が低そうな前者の手法が
いいと思います。
それからサウンドの制御で PlayMusic()/PlaySound()の一発コールで
再生ができるタイプと PlaySoundMem()などのサウンドハンドルを用いるタイプと
2つの選択肢がありますが、いろいろ考えると細かくパラメータを制御できる
サウンドハンドルを用いた方法の方がいいでしょう。
ただ、サウンドデータのメモリへの読み込みに LoadSoundMem()を使ってしまうと
曲ファイルの読み込みが完了復帰(読み込みが全て完了するまでメインの処理が
全て停まる)で処理されるので、スレッドを立てて自前でメインの処理を止めないように
メモリに読み込み、LoadSoundMemByMemImage()を使ってサウンドハンドル化する、
という方法にする必要がありそうです。
あとはゲームにおける曲の切り換えはフェードイン・フェードアウトを伴うことが
比較的多いかと思います。
更には同時にフェードイン・フェードアウトが発生することもありそうです。
例えば曲1(M1)を再生中に曲2(M2)の曲を再生する場合、M2をメモリに
読み込んでから M1の曲のボリュームを 100%から 0%に向かって下げつつ、
同時に M2のボリュームを 0%から 100%に上げる、とか。
なので、曲制御のシステムは(ゲームで使われそうな)そういう用途を念頭に置いて
設計した方がいいと思います。
これは Dxライブラリの話と考えていいのでしょうか?
仮にそうだとして、 PlayMusic()/PlaySound()関数の mp3/oggなどの再生は
内部で指定したファイルを丸ごとメモリに読み込んで、それから再生を始めます。
再生処理そのものは DirectSoundで行っており、多分ですが再生している
ところより少し先を mp3/oggから生の wavに変換して順次再生しているはずです。
なので、mp3/oggファイルそのものはメモリに展開されていますが、
直で再生可能なナマの wavへの展開は再生に必要な部分だけとなります。
>もしそうだとすると、あまりたくさんの曲データをいれてしまうと
>とんでもないことになるので
ハードディスクの方はたくさん曲があると大変なことになるかもしれませんが、
PlayMusic()/PlaySound()に限って言えば、同時に1曲しか再生できない仕様になっていて、
その制限から、過去に再生していたデータはメモリ上から消していますので、
メモリ的には1曲分しか消費しません。
なので、1曲が数十MB以上あるとかじゃない限り、そうそう心配はないかと思います。
(PlayMusic()ではなく、PlaySoundMem()などの自分でサウンドの状態を管理する場合は
勝手にメモリから消えたりはしないので注意が必要です。)
>皆さんがゲームを作るときはどのようにされているのでしょうか?
Dxライブラリはほとんどまともに使ったことがないので、参考になるかどうかわかりませんが。
Midiにするか mp3にするかは音質とゲームの総容量と相談ですね。
メモリに対する基本戦略はとりあえず本当に必要になるまで読み込まないか、
問答無用で全部最初に読み込んでおく、のどちらかになるかと思います。
どちらも一長一短ですが、個人的には無駄なメモリを喰わない&後から
「メモリ食い過ぎ!」状態になって後悔する可能性が低そうな前者の手法が
いいと思います。
それからサウンドの制御で PlayMusic()/PlaySound()の一発コールで
再生ができるタイプと PlaySoundMem()などのサウンドハンドルを用いるタイプと
2つの選択肢がありますが、いろいろ考えると細かくパラメータを制御できる
サウンドハンドルを用いた方法の方がいいでしょう。
ただ、サウンドデータのメモリへの読み込みに LoadSoundMem()を使ってしまうと
曲ファイルの読み込みが完了復帰(読み込みが全て完了するまでメインの処理が
全て停まる)で処理されるので、スレッドを立てて自前でメインの処理を止めないように
メモリに読み込み、LoadSoundMemByMemImage()を使ってサウンドハンドル化する、
という方法にする必要がありそうです。
あとはゲームにおける曲の切り換えはフェードイン・フェードアウトを伴うことが
比較的多いかと思います。
更には同時にフェードイン・フェードアウトが発生することもありそうです。
例えば曲1(M1)を再生中に曲2(M2)の曲を再生する場合、M2をメモリに
読み込んでから M1の曲のボリュームを 100%から 0%に向かって下げつつ、
同時に M2のボリュームを 0%から 100%に上げる、とか。
なので、曲制御のシステムは(ゲームで使われそうな)そういう用途を念頭に置いて
設計した方がいいと思います。
Re:BGMについて
早速の回答ありがとうございます!
私はDXライブラリを使用しています。
>サウンドデータのメモリへの読み込みに LoadSoundMem()を使ってしまうと
曲ファイルの読み込みが完了復帰(読み込みが全て完了するまでメインの処理が
全て停まる)で処理される
音楽ファイルを必要な時にのみ読込むようにすると、目に見える形で動きが止まっていたのはそういうことだった
んですね。
>メインの処理を止めないようにメモリに読み込み
ファイルから数バイト読み込んで、メインループに戻すという作業を繰り返す・・・ということでOKでしょうか?
こういう作業はまだやったことがないのですが、難しそうですね。
私はDXライブラリを使用しています。
>サウンドデータのメモリへの読み込みに LoadSoundMem()を使ってしまうと
曲ファイルの読み込みが完了復帰(読み込みが全て完了するまでメインの処理が
全て停まる)で処理される
音楽ファイルを必要な時にのみ読込むようにすると、目に見える形で動きが止まっていたのはそういうことだった
んですね。
>メインの処理を止めないようにメモリに読み込み
ファイルから数バイト読み込んで、メインループに戻すという作業を繰り返す・・・ということでOKでしょうか?
こういう作業はまだやったことがないのですが、難しそうですね。
Re:BGMについて
>ファイルから数バイト読み込んで、メインループに戻すという作業を繰り返す・・・ということでOKでしょうか?
それでもいいのですが、それだと1回に何バイト読み込めばいいのかを決めるのに苦労しそうです。
なので「マルチスレッド」を使って、メインの処理に影響の無い範囲で
メインの処理と並列に(厳密には並列ではないですが)ファイルを読むと
いいんじゃないだろうか、ということです。
詳しくはマルチスレッド、CreateThreadなどでググってみて下さい。
ただ、ちょっと難しい処理ですし、ゲームの本筋とは関係ない部分もないので、
ここで悩むよりゲーム本編の処理で悩んだ方がよっぽど為になります。
最初の内は気にしないで普通に(多少画面が止まっても気にしないで)組んでみた方が
いいと思います。
それでもいいのですが、それだと1回に何バイト読み込めばいいのかを決めるのに苦労しそうです。
なので「マルチスレッド」を使って、メインの処理に影響の無い範囲で
メインの処理と並列に(厳密には並列ではないですが)ファイルを読むと
いいんじゃないだろうか、ということです。
詳しくはマルチスレッド、CreateThreadなどでググってみて下さい。
ただ、ちょっと難しい処理ですし、ゲームの本筋とは関係ない部分もないので、
ここで悩むよりゲーム本編の処理で悩んだ方がよっぽど為になります。
最初の内は気にしないで普通に(多少画面が止まっても気にしないで)組んでみた方が
いいと思います。
Re:BGMについて
さっそく「マルチスレッド」でググッてみました。
書いてある事(理屈)は何となくわかるのですが、難しそうですね。
Justy さんのおっしゃる通り、とりあえず今は後回しにします。
もう少しメインの処理をしっかりさせて、経験を積んでから勉強しなおしたいと思います。
ありがとうございました。
書いてある事(理屈)は何となくわかるのですが、難しそうですね。
Justy さんのおっしゃる通り、とりあえず今は後回しにします。
もう少しメインの処理をしっかりさせて、経験を積んでから勉強しなおしたいと思います。
ありがとうございました。