久しぶりの質問です。
mciSendString または mciSendCommand を使って、Midiファイルを演奏したいのですが、
デバイスオープン処理に時間がかかってしまい、困っています。
この時間を短縮させたいのですが、いい方法はありますでしょうか?
開発環境はVC++2005、OSはWinXPです。
以下のように、「デバイスオープン」→「Midiファイル再生」の合間にTRACE文を出力さ
せて処理時間を計測しました。
結果、「Midi Open !!!!」~「Midi Start !!!!」が表示されるまでの時間(つまりデバ
イスオープンの所要時間)が、けっこうかかってしまいます。
PCの性能もあるかもしれませんが、Midiファイルのサイズが大きいほど時間がかかり、
60KBで約3秒ほどです。
ソフトはスピードも命なので、この時間はけっこうストレスです。
手持ちの本によると、「デバイスオープン時にMCI_WAITを指定すると、MCIの実行完了ま
で待機する」そうですね。
ということは逆に、「MCI_WAITを指定しなければ待機しない(つまり時間差はかからな
い)」はずですよね?
ところが実際は、MCI_WAITを指定してもしなくても、所要時間がかかってしまいます。そ
こも疑問の一つです。
Midiファイルを軽量化するのも一つの手ですが、音楽の質は落としたくないし、根本的な
解決策ではないと思います。
もしくはマルチスレッドにすることも検討中ですが…。
以下、実際のソースコードです。よろしくお願いします。
MCI_PLAY_PARMS parms;
MCIERROR error;
char buf[129];
TRACE(Midi Open !!!!n);
// デバイスオープン
midi_parms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_SEQUENCER;
midi_parms.lpstrElementName = ongaku.mid;
if (error = mciSendCommand(
0, MCI_OPEN,
MCI_OPEN_TYPE|MCI_OPEN_ELEMENT|MCI_OPEN_TYPE_ID,
(DWORD)&midi_parms)) {
mciGetErrorString(error, buf, sizeof(buf));
TRACE(Midi Open Error!!! (%s)\n, buf);
return;
}
MidiNo = NewMidiNo;
TRACE(Midi Start !!!!\n);
// Midiファイル再生
parms.dwFrom = 0;
if (error = mciSendCommand(midi_parms.wDeviceID, MCI_PLAY, 0, (DWORD)
&parms)) {
mciGetErrorString(error, buf, sizeof(buf));
TRACE(Midi Play Error!!! (%s)\n, buf);
return;
}
TRACE(Midi OK !!!!\n);
あまり詳しくありませんが・・。
MCI_OPEN時にファイルを指定するのをやめて、
MCI_LOADで別途ファイルをロードしてみるのはどうでしょう。
これがうまく動作するのなら、かつ、OPENに時間がかかっているのなら、
デバイスIDを保存的に運用(開きっぱなしに)することで、
OPENの時間を節約できるかもしれません。
うまくいかなかったらご容赦ください。
仲澤さんの意見に賛成ですね。
このタイプは初期化に時間がかかるのだと思います。
メインルーチンが立ち上がる前に「MIDI OPEN」の処理を行うようにしたほうが
いいと思います。
ファイルの読込みは、仲澤さんの意見どおり「MCI_LOAD」を使うのがいいと
思います。
「MIDI CLOSE」は、プログラム終了時に処理することでいいと思います。
あと、重たいソフトウエア音源だとPCの能力に関わってきてしまう
ので、デバイスの選択はオペレータにまかせた方がいいですね。
(最近のPCは速いのでそんなことはないかな?........)
仲澤さん、ITOさん、ご回答ありがとうございます。
現状、BGMを切り替えるたびに、デバイスのオープンとクローズを行ってますが、そう
ではなく、
「デバイスはオープンしっぱなしにして、BGMの切り替えはロードのみにする」という
ことですね?
しかしこの方法で処理速度がどの程度向上するかは疑問です。
というのも、処理時間の大きさはMidiファイルのサイズに依存しているからです。
ファイルサイズが1KB程度ですとストレスなく切り替わりますが、60KBだと3~5秒ほど処
理時間がかかってしまいます。
ということは、「デバイスのオープン処理そのものに時間がかかっているのではなく、
Midiファイルの読み込みに時間がかかっている」と推測されます。
であるならば、ご提示いただいた方法で解決するとは思えないのですが…。
当方、MCI_LOADを使った方法については不勉強ゆえ、試すとなると調査が必要となりま
す。
すみませんが、この方法で解決すると思われる理由を、お聞かせいただけませんでしょう
か?
>ということは、「デバイスのオープン処理そのものに時間がかかっているのではなく、
>Midiファイルの読み込みに時間がかかっている」と推測されます。
自分の発言において、不確かではあるものの、アイデアは示しました。
それが、おっしゃる通り「根拠がない」と批判されるのであれば、
「ファイルロードに時間がかかっている」とのまにさんの意見も
現時点では「推測」にすぎませんよね(笑)。
「証拠を示せ」といわれても、多分誰もやってくれないと思いますよ。他人事だし。
ご自身で検証してみるか、はっきりとあきらめて降参し、
もっとましな事を始めるかの二択だと思うのですが、いかがでしょう。
仲澤さん、不快に思われたのでしたらすみません。
仰るとおり推測ですが、「根拠ある推測」であること、ご理解ください。
アイデアを提示していただいたことに対しては感謝しております。
ですがそれを試すかどうかは、慎重に検討させていただきたいのです。
どのくらい時間がかかるものかとやってみました。
1時間程度ですね。
結果はおしらせできません。あしからず。
ケンカしに書き込みしてるわけではありません。真剣に解決策を求めています。
ただし「真剣さ」とは、「なんでもかんでも試してみること」ではないこと、ご理解くだ
さい。
仲澤さんのご提案で解決するのであれば、なぜ所理時間がファイルサイズに依存するの
か?
この疑問が解けない限り、申し訳ないのですが試してみようとは思えません。
引き続き、他の方のご回答を期待します。
それにしてもなぜ、MCIはこんなにも処理時間がかかるのかが、そもそも疑問です。
Windows Media Playerで再生するときは、100KB以上あるファイルも、すぐに演奏始まる
のに…。
こういうことは本でも分からないし、ネットで調べても(調べ方が悪いのか)答えが見つ
からないんですよね…。
>仰るとおり推測ですが、「根拠ある推測」であること、ご理解ください。
推測にせよ根拠を示すことは大変なことだと思います。
特に処理時間に関することは大変ですね。
今回の場合、「根拠を示す」ためにはマイクロソフトのサポート情報を検索する
以外にないと思います。
>ただし「真剣さ」とは、「なんでもかんでも試してみること」ではないこと、ご理解く
>ださい。
うーーん、
解決策が見つからない以上、ある程度試してみるのも必要だと思います。
もちろん、リスクを伴わないようにためコピーして調査用のプロジェクトを
作るぐらいの努力は必要だと思います。
>この疑問が解けない限り、申し訳ないのですが試してみようとは思えません。
「まにさん自身が、疑問が解くためにいろいろ試す。」だと思います。
私は仲澤さんのご提案ではうまく行かないと考えておりますし、その根拠も示していま
す。
「うまくいく」と主張なされるのであれば、その根拠を示すべきは、私ではなく主張する
側だと思います。
ただし、「主張するかどうか」は自由ですので、「根拠を示すかどうか」も自由ですけど
ね。
うーーん、
まにさんも根拠を示してないですね。
「根拠を示す」ためには、マイクロソフトのサイトなりのくつがえせない証拠が
必要ですね。
いくら推測とはいえ、「根拠を示す」とはそういう意味合いを含んでいます。
ただ、
「家のPCで試してみました。」
ではだめです。
まにさんが、
「根拠を示した事項でないと納得しない。」
のであれば誰もアドバイスしてくれないと思います。
> ということは、「デバイスのオープン処理そのものに時間がかかっているのではな
く、
> Midiファイルの読み込みに時間がかかっている」と推測されます。
であるなら、その時間のかかるMidiファイルの読み込みを先に済ませておけば
MCI_PLAYに即時反応してくれるんじゃなかろか。
と、みなさん仰ってますし、僕もそう思う。
επιστημηさん、ご回答ありがとうございます。
問題点は、「BGMの切り替えに処理時間がかかってしまう」という点です。
たとえば演奏したいMidiファイルが3種類あるとし、それぞれBgmA、BgmB、BgmCと呼ぶこ
とにします。
これを、BgmA→BgmB→BgmC→…と、演奏を切り替えるとします。
現状、以下の手順で演奏を切り替えています。
Midiオープン&BgmA読込
↓
BgmA演奏
↓
Midiクローズ
↓
Midiオープン&BgmB読込
↓
BgmB演奏
↓
Midiクローズ
↓
Midiオープン&BgmC読込
↓
BgmC演奏
↓
Midiクローズ
↓
仲澤さんのご提案は、以下の手順と認識しております。
(Midiクローズはプログラム終了時にのみ行う)
Midiオープン
↓
BgmA読込
↓
BgmA演奏
↓
BgmA停止(この処理は必要か不明)
↓
BgmB読込
↓
BgmB演奏
↓
BgmB停止(この処理は必要か不明)
↓
BgmC読込
↓
BgmC演奏
↓
BgmC停止(この処理は必要か不明)
↓
上記手順では、オープンとクローズを短縮できますが、
Bgmの読み込みに時間がかかるのであれば大した改善にはならないと私は考えておりま
す。
確認させていただきたいのですが、επιστημηさんのご提案は、こうでしょうか?
Midiオープン
↓
BgmA読込
BgmB読込
BgmC読込
↓
BgmA演奏
↓
BgmB演奏
↓
BgmC演奏
↓
切り替えに時間がかかるのであれば YES。
「切り替えに時間がかかるのであれば」ということは、本来はどのような意味で仰られた
のですか?