mciSendStringおよびmciSendCommandで、音楽演奏処理を高速化するには?

[戻る]
まに 2013/02/27(水) 13:50:20
久しぶりの質問です。
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");

仲澤@失業者 2013/02/27(水) 15:07:01
あまり詳しくありませんが・・。

MCI_OPEN時にファイルを指定するのをやめて、
MCI_LOADで別途ファイルをロードしてみるのはどうでしょう。
これがうまく動作するのなら、かつ、OPENに時間がかかっているのなら、
デバイスIDを保存的に運用(開きっぱなしに)することで、
OPENの時間を節約できるかもしれません。

うまくいかなかったらご容赦ください。

ITO 2013/02/28(木) 17:36:27
 仲澤さんの意見に賛成ですね。
このタイプは初期化に時間がかかるのだと思います。
 メインルーチンが立ち上がる前に「MIDI OPEN」の処理を行うようにしたほうが
いいと思います。
 ファイルの読込みは、仲澤さんの意見どおり「MCI_LOAD」を使うのがいいと
思います。
「MIDI CLOSE」は、プログラム終了時に処理することでいいと思います。
  あと、重たいソフトウエア音源だとPCの能力に関わってきてしまう
 ので、デバイスの選択はオペレータにまかせた方がいいですね。
  (最近のPCは速いのでそんなことはないかな?........)


  

まに 2013/03/01(金) 16:56:01
仲澤さん、ITOさん、ご回答ありがとうございます。
現状、BGMを切り替えるたびに、デバイスのオープンとクローズを行ってますが、そう
ではなく、
「デバイスはオープンしっぱなしにして、BGMの切り替えはロードのみにする」という
ことですね?

しかしこの方法で処理速度がどの程度向上するかは疑問です。
というのも、処理時間の大きさはMidiファイルのサイズに依存しているからです。
ファイルサイズが1KB程度ですとストレスなく切り替わりますが、60KBだと3〜5秒ほど処
理時間がかかってしまいます。
ということは、「デバイスのオープン処理そのものに時間がかかっているのではなく、
Midiファイルの読み込みに時間がかかっている」と推測されます。
であるならば、ご提示いただいた方法で解決するとは思えないのですが…。

当方、MCI_LOADを使った方法については不勉強ゆえ、試すとなると調査が必要となりま
す。
すみませんが、この方法で解決すると思われる理由を、お聞かせいただけませんでしょう
か?

仲澤@失業者 2013/03/01(金) 17:55:27
>ということは、「デバイスのオープン処理そのものに時間がかかっているのではなく、
>Midiファイルの読み込みに時間がかかっている」と推測されます。

自分の発言において、不確かではあるものの、アイデアは示しました。
それが、おっしゃる通り「根拠がない」と批判されるのであれば、
「ファイルロードに時間がかかっている」とのまにさんの意見も
現時点では「推測」にすぎませんよね(笑)。
「証拠を示せ」といわれても、多分誰もやってくれないと思いますよ。他人事だし。

ご自身で検証してみるか、はっきりとあきらめて降参し、
もっとましな事を始めるかの二択だと思うのですが、いかがでしょう。

まに 2013/03/02(土) 20:05:32
仲澤さん、不快に思われたのでしたらすみません。
仰るとおり推測ですが、「根拠ある推測」であること、ご理解ください。
アイデアを提示していただいたことに対しては感謝しております。
ですがそれを試すかどうかは、慎重に検討させていただきたいのです。

仲澤@失業者 2013/03/03(日) 14:08:28
どのくらい時間がかかるものかとやってみました。
1時間程度ですね。
結果はおしらせできません。あしからず。

まに 2013/03/04(月) 20:43:33
ケンカしに書き込みしてるわけではありません。真剣に解決策を求めています。
ただし「真剣さ」とは、「なんでもかんでも試してみること」ではないこと、ご理解くだ
さい。
仲澤さんのご提案で解決するのであれば、なぜ所理時間がファイルサイズに依存するの
か?
この疑問が解けない限り、申し訳ないのですが試してみようとは思えません。
引き続き、他の方のご回答を期待します。

それにしてもなぜ、MCIはこんなにも処理時間がかかるのかが、そもそも疑問です。
Windows Media Playerで再生するときは、100KB以上あるファイルも、すぐに演奏始まる
のに…。
こういうことは本でも分からないし、ネットで調べても(調べ方が悪いのか)答えが見つ
からないんですよね…。

ITO 2013/03/07(木) 12:09:32
>仰るとおり推測ですが、「根拠ある推測」であること、ご理解ください。
推測にせよ根拠を示すことは大変なことだと思います。
特に処理時間に関することは大変ですね。
 今回の場合、「根拠を示す」ためにはマイクロソフトのサポート情報を検索する
以外にないと思います。

>ただし「真剣さ」とは、「なんでもかんでも試してみること」ではないこと、ご理解く
>ださい。
うーーん、
 解決策が見つからない以上、ある程度試してみるのも必要だと思います。
 もちろん、リスクを伴わないようにためコピーして調査用のプロジェクトを
作るぐらいの努力は必要だと思います。
>この疑問が解けない限り、申し訳ないのですが試してみようとは思えません。
「まにさん自身が、疑問が解くためにいろいろ試す。」だと思います。

まに 2013/03/08(金) 21:25:38
私は仲澤さんのご提案ではうまく行かないと考えておりますし、その根拠も示していま
す。
「うまくいく」と主張なされるのであれば、その根拠を示すべきは、私ではなく主張する
側だと思います。
ただし、「主張するかどうか」は自由ですので、「根拠を示すかどうか」も自由ですけど
ね。

ITO 2013/03/10(日) 17:45:58
うーーん、
 まにさんも根拠を示してないですね。
「根拠を示す」ためには、マイクロソフトのサイトなりのくつがえせない証拠が
必要ですね。
いくら推測とはいえ、「根拠を示す」とはそういう意味合いを含んでいます。
ただ、
  「家のPCで試してみました。」
ではだめです。

まにさんが、
  「根拠を示した事項でないと納得しない。」
のであれば誰もアドバイスしてくれないと思います。

επιστημη [E-Mail] [HomePage] 2013/03/10(日) 22:41:09
> ということは、「デバイスのオープン処理そのものに時間がかかっているのではな
く、
> Midiファイルの読み込みに時間がかかっている」と推測されます。

であるなら、その"時間のかかるMidiファイルの読み込み"を先に済ませておけば
 MCI_PLAYに即時反応してくれるんじゃなかろか。

と、みなさん仰ってますし、僕もそう思う。

まに 2013/03/11(月) 21:21:46
επιστημηさん、ご回答ありがとうございます。

問題点は、「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演奏
↓

επιστημη [E-Mail] [HomePage] 2013/03/11(月) 21:35:35
切り替えに時間がかかるのであれば YES。

まに 2013/03/12(火) 21:02:20
「切り替えに時間がかかるのであれば」ということは、本来はどのような意味で仰られた
のですか?

επιστημη [E-Mail] [HomePage] 2013/03/13(水) 05:50:14
「切り替えに時間がかかる」
→切り替えを処理の途中に挟むわけにはいかない
→あらかじめ読んでおけばいいんじゃない?
てことで。

もちろんこれでうまくいくかはわからんですが、
「やってみたくない」なら勝手にしろ、です。

まに 2013/03/13(水) 21:42:42
επιστημηさんのご提案は、「Midiファイルの読み込みを、BGM切り替えの都度行
うか?一度だけ行うか?」の違いですね?
現状、切り替えの都度行っているので、もし一度で済むのであれば全体的には処理時間の
短縮が図れます。(それが可能かどうかは、調査が必要ですが。)
しかし、Midiファイルの読み込み処理時間そのものを短縮させたいので、申し訳ないです
が根本的な解決策にはならないと思います。
他の方法を検討してみます。

ITOさん
>「根拠を示す」ためには、マイクロソフトのサイトなりのくつがえせない証拠が必要で
すね。
根拠にも、「程度」ってのがありますよね?
そこまで厳密な根拠は求めてません。
「試す価値がある」と言える根拠を求めています。
現状、「試しても無駄」と思える根拠の方が、勝ってますよね?

ホウジョウウサギ 2013/03/14(木) 10:07:26
横から失礼しますが…
喧嘩腰(?)になる前に,本当に問題としていることが何なのか?を
はっきりさせたほうがよいのではないでしょうか?


2013/03/11(月) 21:21:46 の発言では,
>問題点は、「BGMの切り替えに処理時間がかかってしまう」という点です。
とおっしゃられていて,私がこの文面を読んだ感じでは,例えば
{ゲームか何かでシーンの切り替え時にBGMを変えたいが,そのときに毎回数秒程度固
まってしまう}
という類のことを問題にしているように見受けました.
(Win98時代のフリーソフトなんかをXPとかで動かしたりするとこの現象に出くわしたりし
ますね)
おそらく他の方々もこのような受け取り方をされており,アイデアが示されています.

しかしながら,2013/03/13(水) 21:42:42 では,
>Midiファイルの読み込み処理時間そのものを短縮させたい
のであって,
「全体的な処理時間の短縮」が目的なのではない,と.つまり結局のところ
{アプリケーション開始時刻〜初回のBGMの演奏開始時刻 までの時間}を問題にしてい
る,ということでしょうか?


仮に後者なのだとして,
>Midiファイルのサイズが大きいほど時間がかかり
ということであって,かつ,他の方々が示しているような先行ロードを行った場合に演奏
するMIDIの切り替えがノータイムでスムーズにいくのであれば…

(MIDIファイルがこういうことができるのかどうかわかりませんが)
演奏したいMIDIファイルをいくつかに細切れにしておけばどうでしょう?
例えば{A,B,C}に3分割したとして,
・Aをロード(分割前の1/3の時間で済む?)→演奏開始
・Aの演奏中に別途Bをロードしておく
・Aの演奏終了時にBの演奏を開始(切り替え)
・Bの演奏中に別途Cをロード…
みたいな.

わんこ 2013/03/14(木) 13:21:28
http://www.activebasic.com/forum/viewtopic.php?t=99&sid=9dc2affab12b65c1d2f12695c7281fa9

この人と同じような現象でしょうか?

επιστημη 2013/03/14(木) 15:09:39
> Midiファイルの読み込み処理時間そのものを短縮させたいので、申し訳ないです

が根本的な解決策にはならないと思います。



後出しジャンケンかよー orz



> 問題点は、「BGMの切り替えに処理時間がかかってしまう」という点です。



って言うたやんかー...

ITO 2013/03/14(木) 21:32:37
>「試す価値がある」と言える根拠を求めています。
> 現状、「試しても無駄」と思える根拠の方が、勝ってますよね?

うーーん、
「試しても無駄」なら試さなければいいだけです。
 そういうきつい断り方でなくでなく、
  「せっかく意見をもらいましたが、もう少し検討します。」
 というような穏やかな断り方をかんえたほうがいいですね。
 
  試す価値がある/ないは、まにさんの勝手の判断です。
  「試す価値がないので試しません。」
 のまにさんの一言で終わりです。
そこに他人から「根拠」を要求するのはおかしいですね。

>ということは、「デバイスのオープン処理そのものに時間がかかっているのではなく、
>Midiファイルの読み込みに時間がかかっている」と推測されます。
 これに、試す価値があるというのであれば試して、結果を掲示して意見を
求めたらどうでしょうか。



 
 

そろそろ 2013/03/14(木) 23:24:57
解決方法が知りたいのか原因が知りたいのかどっちなんでしょう
解決方法なら試してみないといけませんし、原因が知りたいなら
インシデントでも使ってMSに聞けということでしょう。
論破?した所で回答者には痛くも痒くもありませんし。

#楽しいレスのせいで結構損しているような気がしてますけど
#まぁ自分で解決すれば良いんじゃないですかね。

まに 2013/03/15(金) 14:29:10
根本的解決は、「Midi再生に要する処理時間を短縮させること」です。
その解決策を探る手がかりになるのであれば、なぜ処理時間がかかるのか、その原因も知
りたいです。
たとえ根本的解決策でなくとも、要はユーザーに待ち時間を感じさせなければいいわけな
ので、
επιστημηさん、ホウジョウウサギさんご提案の方法は、その一つの手段ですね。

ちなみに「BGM切り替え」とは、「初回BGM演奏時」も含みます。
3月11日の書き込みはそういう意味で言ったのですが、混乱を招く表現でした。失礼しま
した。
ただ、プログラム起動と同時にBGMを再生したいので、επιστημηさんご提案の方
法ではちょっと…。

わんこさんのリンク先、拝見しました。そうです、この方と同じ問題です。
ですが試してみましたが、うまく行きませんでした。
MPEGVideoデバイスの指定「Midi.lpstrDeviceType = "MPEGVideo";」をやってみたのです
が、
「指定されたファイル名拡張子からデバイス種別を判断できません」というエラーになり
ます。
「ファイル名拡張子」と言ってるということは、「mpegなら再生できる」ということか?
と思い、
ネットから拡張子「mpg」のファイルをダウンロードし試してみましたが、結果は同じで
した。
おそらく「MPEGVideo」という文字が認識されてないのではと思います。

自分でも調べてみたのですが、どうやらMCIは高水準のコントロールのようです。
時間がかかってしまうのはそのせいかもしれませんね。
ということは、低水準のコントロールを使えば解決するのではないかと考えています。
もう少し調べてみます。

επιστημη [E-Mail] [HomePage] 2013/03/15(金) 17:01:06
midiは言わば"楽譜"だから相応の処理が必要かと思う。
一旦"音"、すなわちwavに変換しちまえば速度的には改善
されるハズなんだけども、その解はナシですか?

そもそも 2013/03/16(土) 02:03:26
簡単に再現できる最低限のソースを提示して頂いた方が
なんとなく早道な気がするのですけど。
あとOSとかVSのバージョンとか

Ryo 2013/03/19(火) 00:51:41
>→あらかじめ読んでおけばいいんじゃない?

に対して、

>ただ、プログラム起動と同時にBGMを再生したいので、επιστημηさんご提案の
方法ではちょっと…。

と返しているわけだから

プログラム起動時の初期化のための時間なしで
たとえば、exeファイルをダブルクリックした直後に、大きいサイズのmidiを鳴らしたい
ってことか…

tarou 2013/03/19(火) 09:05:44
mciでのMIDI再生は遅いというのはどうすることも出来なく、
早くしたい場合は自力でmidファイルを読み込んで解析して
MIDI APIを使って再生する必要があるそうです

参考
ttp://eternalwindows.jp/winmm/midi/midi00.html

辿って全部読んでください
やらなければいけない事は全て書いてあると思います

まに 2013/03/19(火) 18:14:14
tarouさん、リンク先ご提示、ありがとうございます。まさに求めていた情報です。リン
ク先、印刷してざっと拝読しました。

確かに、このサイトには「MCIは高水準のため時間がかかる」と明言してありますね。と
はいえ低水準でやるとなると、MIDIの中身を解析して自分で音を鳴らす…そこまでやらな
いとならないとは…!!ざっと読んでみたけど、挫折しそうです……。そこまでしてBGM演奏
を高速化するかどうか…悩むところです。
疑問なんですが、自作ソフトで音を鳴らす他の方々は、皆そこまでなさってらっしゃるん
でしょうか…?

自作ソフトに組み込むのではなく、Midi演奏専用のソフトが、あればいいんですけどね。
そのソフトを別途起動し、BGM演奏はすべてそのソフトにまかせる。あとは「どの曲を再
生しろ」「停止しろ」「終了しろ」という指示をWindowsメッセージで送ってやればいい
だけ。せめて、そんなソフトが、あってもよさそうなもんなんですけど、ないものなんで
しょうか?
まぁそれがMCIなんでしょうけど、あの処理時間の遅さは致命的ですからね。

επιστημη [E-Mail] [HomePage] 2013/03/20(水) 10:46:22
> そこまでしてBGM演奏を高速化するかどうか…悩むところです。

いやだから、そこまでしてMIDIじゃなきゃあかんですか?

ITO 2013/03/21(木) 12:25:45
>疑問なんですが、自作ソフトで音を鳴らす他の方々は、皆そこまでなさってらっしゃる
>んでしょうか…?
んー
MIDIの演奏にこだわる人は、MIDI-APIを使っていますね。
普通は、MCI使うか、επιστημηさんの意見どおりWAVファイルに変換して
WAVファイルを再生するかですね。
ゲーム系ならダイレクトサウンド関連を使うのだと思います。
ただmidiファイルが使えるは確認ください。


>まぁそれがMCIなんでしょうけど、あの処理時間の遅さは致命的ですからね。
>Midiファイルのサイズが大きいほど時間がかかり、60KBで約3秒ほどです。
まぁー高水準なら仕方ないのではないでしょうか。
MIDIファイルを解析してMIDI-APIを使ってリアルタイムで演奏することを考えると、
60KBで3秒はいいせんいっているのではないでしょうか。

>Windows Media Playerで再生するときは、100KB以上あるファイルも、すぐに演奏始ま
>るのに…。
Windows Media Player SDKを使ってるのはどうですか。
http://msdn.microsoft.com/ja-jp/library/dd148616.aspx

ITO 2013/03/21(木) 12:39:58
修正・追記
>Windows Media Player SDKを使ってるのはどうですか。
Windows Media Player SDKを使うのはどうですか。

 MIDIファイルにこだわらないのなら、WAVファイルに変換してWAVファイルを再生が
いいと思いますね。

ITO 2013/03/21(木) 17:33:10
僕とεπιστημηさんの意見
midi wav 変換ツールがあるので変換してWAVで再生したらいいと思います。
http://search.vector.co.jp/vsearch/vsearch.php?key=midi+wav+%E5%A4%89%E6%8F%9B%
22

まに 2013/03/21(木) 19:30:00
[[解決]]
皆さん、ありがとうございました。
わんこさんのリンク先の方法で、解決しました。
最初うまくいかなかったのは、パラメータが間違ってたからでした。失礼しました。いざ
解決してみたら、あれだけ時間かかってたのがウソみたいに、あっけなくBGMが鳴りまし
た。あまりにもあっけなさすぎて「これでいいのか?」って思えてしまうほどです。

MidiをWaveに変換するアイデアも試してみましたが、やはりファイルサイズが肥大します
ね…。BGMをWaveで鳴らすソフト見かけたことありませんが、一般的な方法なんでしょう
か?

「Windows Media Player SDKを使う」というのは、「Midi演奏専用のソフトを別途起動
し、BGM演奏はすべてそのソフトにまかせる」ということでしょうか?

いずれにせよ、時間がかかるという問題はクリアしたので、解決とさせていただきます。
わんこさんはじめ、皆さん、本当にありがとうございました。

古いスレッドには追加発言できません。