一括表示
タイトル
記事No
投稿日
投稿者
参照先
KbMedia Player Version 3.12beta2.2024.0301
255
2024/03/01(Fri) 02:05:27
Kobarin

https://kobarin.sakura.ne.jp/test/kbmed312_beta2.exe
https://kobarin.sakura.ne.jp/test/kbmed312_beta2.7z

.exe と .7z はどちらも中身は同じです。
.7z の展開の仕方が分からない方は .exe をダウンロードして下さい。

.exe だと Microsoft Edge でブロックされる方は .7z をダウンロードして下さい。
Microsoft Edge にブロックされる方は安全だと報告してくれると助かります。

起動時にエラーメッセージが表示されてプラグインが認識されない場合は
Microsoft Visual C++ 2022 再頒布可能パッケージが必要です。
https://visualstudio.microsoft.com/ja/downloads/#other-ja-family
x64 版ランタイムファイル直リンク
https://aka.ms/vs/17/release/VC_redist.x64.exe
x86 版ランタイムファイル直リンク
https://aka.ms/vs/17/release/VC_redist.x86.exe
(x64 版の動作には vc_redist.x64.exe と vc_redist.x86.exe の両方が必要です)

VS2019 のランタイムでも動作はするようですが、念のため VS2022 の
ランタイムを入れて下さい。Windows XP 環境の人は除きます。

Windows XP で使いたい方は

https://kobarin.sakura.ne.jp/wforum/wforum.cgi?mode=read&no=181&reno=180&oya=180&page=0#181

こちらを参考にして古いランタイムをインストールして下さい。一応まだ
XP でも動作するようです。


v3.12beta2 での変更点

・各種プラグイン/DLL の開発環境を VS2022 17.9.1 に更新
・GuruGuruSMF4.dll を使用して DirectMusic で MIDI を再生する演奏プラグイン
 kbGuru2SMF.kpi を同梱
 ・You さんがサポート掲示板で公開された v0.01 を Kobarin が引き継ぐ
・kbGuru2SMF.kpi に関する以下の修正(掲示板で公開された v0.01 からの変更点)
 ・You さん製作の kbGuru2SMF.kpi v0.01 の開発を Kobarin が引き継ぐ
 ・GuruGuruSMF4.dll を v4.0.6 から v4.0.7(を VS2022 でビルドしたもの)に変更
 ・GuruGuruSMF4.dll を LoadLibrary して使うようにした
 ・GuruGuruSMF4.dll に対する以下の修正
  ・VS2022 でビルド
  ・メモリリーク修正
  ・スリープ時にデバイスを閉じる処理が原因と思われる不具合(FreeLibrary 時にフ
   リーズ)の修正
  ・↑の為、GuruGuruSMF4.dll に後始末用API(GGS4Uninialize_k) を追加(他に方法
   が思いつかなかった)
 ・GuruGuruSMF4.dll のパスを設定出来るようにした
  ・オリジナルの v4.0.7 は正常動作しない(v4.0.6 なら動作する)
・kbfmp.kpi に関する以下の修正
 ・64bit版 WinFMP.dll が公開されたことに伴い、64bit 版の kbfmp.kpi_ のファイル
  名を kbfmp.kpi に変更
・kbviv.kpi に関する以下の修正
 ・本体の CoInitializeEx の呼び出しの有無やパラメータによらず動作するようにし
  た
・kbpsf2.kpi に関する以下の修正
 ・boost ライブラリを 1.84.0.0 に更新
・ループタグ(LOOPSTART/LOOPLENGTH)を含む曲データのフェードアウト時に落ちること
 があるのを修正
・64bit 版で rcpcv.dll のロードに失敗すると以後 rcpcv.dll を導入しても本体を再
 起動するまでロードしなくなる(バージョン情報ダイアログでは導入済みと表示される
 が正しい情報を表示しない)のを修正
・本体の COM の初期化を STA から MTA に変更
 ・kbviv.kpi が動作しなくなったがプラグイン側で対処


You さんの kbGuru2SMF.kpi を kbdmusic.kpi に組み込もうと思いましたが
kbGuru2SMF.kpi の開発を私が引き継ぐ形を取り、本体に標準同梱することに
しました。

kbGuru2SMF.kpi は配布サイトを置かず、ソース・バイナリ自由に改変して良いとの
ことでしたのでそれで構いませんよね? => You さん

GuruGuruSMF4.dll は v4.0.7 の改造版を同梱しています。
公式版だと FreeLibrary 時にフリーズしますが改造版は大丈夫な筈です。
メモリリーク等、いくつかの不具合も修正しています。

フリーズするのはスリープ時にデバイスを閉じる処理の為のスレッドを DllMain の
DLL_PROCESS_DETACH 内で終了させようとしてるからだと思います。
GuruGuruSMF4.dll に後始末用の API を新設する以外に対処する方法を思いつきません
でした。

kbdmusic.kpi の方はまだ何も手をつけていませんが、本体が COM を MTA で初期化する
ようにしたので kbGuru2SMF.kpi v0.01(GuruGuruSMF4.dll v4.0.6) を使っても動作に
支障は出なくなっています。

GuruGuruSMF4.dll v4.0.7 をベースにしてる kbGuru2SMF.kpi v0.02 の方は本体の
COM の初期化が STA/MTA どちらであっても kbdmusic.kpi の動作には影響しません。

過去にあった要望の対応、他のプラグインのライブラリの更新はこれから少しずつ
進めていきます。
pagetop
タイトル
記事No
投稿日
投稿者
参照先
kbGuru2SMF.kpi v0.02
256
2024/03/01(Fri) 10:47:29
Kobarin

kbGuru2SMF.kpi v0.02 のソース

https://kobarin.sakura.ne.jp/kpi/kbGuru2SMF_002s.7z


GuruGuruSMF4.dll のソースコード改変箇所については

kbGuru2SMF_memo.txt

を参照して下さい。


v4.0.7 がFreeLibrary 時にフリーズする件については、実は VS2022 でビルドした
場合には、その為の対策をしなくても発生を確認出来ていません。

ただ、DllMain 内で出来ることは限られているので、ここで後始末の処理をしている
ことが問題である可能性は非常に高いと考えています。

メモリリークは曲データを1度開く度にサイズが 0 の配列と12バイトの解放し忘れ
なのでとても軽微なものです。発生箇所を特定するのに苦労しましたが。
pagetop
タイトル
記事No
投稿日
投稿者

Re: kbGuru2SMF.kpi v0.02
257
2024/03/02(Sat) 10:41:41
You
更新ありがとうございます。
kbGuru2SMF.kpi の取り込みも本当にありがとうございます。
ソースを引き継いで本体に同梱するのはこちらも想定していた形ですので全く問題ありません。

動作確認してみたところ、kbGuru2SMF.kpi → kbdmusic.kpi の切り替えは問題なく再生されました。
ただ、64bit版本体で起動直後の kbGuru2SMF.kpi の再生や、kbdmusic.kpi → kbGuru2SMF.kpi の切り替え後の再生が出来ないことが有りました。

ソースも公開されているので調査してみたところ、GuruGuruSMF\dxmus.core\Port.cpp に原因がありそうです。
理屈としては起動直後以外のタイミングや32bit版の本体でも発生するはずですが、今のところ発生を確認できていません。
修正したソースを添付しますので確認してみてください。


Port::Open() 内の処理で、PostCommand() でOpenコマンドをキューに追加して
Wait(1) でワーカースレッド Port::OnWorker() の処理完了を待っていますが、
ワーカースレッドが Sleep(1) を実行しているタイミングで Wait(1) が呼ばれると、
処理完了を待たずに Wait(1) を抜けてしまい、その結果未初期化の変数 resultOpen が Port::Open() の戻り値になります。

KbGuru2SMFPlayer::Open() 内で呼んでいる m_pGGS->OpenDevice() の戻り値は未初期化の resultOpen の値がそのまま返されるので
GuruGuruSmf::GgsError::NoError にならず、KbGuru2SMFPlayer::Open() が FALSE を返すことになりそこで処理が中断されます。

対策として、Port::Wait() でスピンロックに使用している isBusy を
true に設定する場所を Port::PostCommand() の commands.push() の直後に移し、
false に設定する場所を Port::OnWorker() の commands.pop() の直後に移すことで、
PostCommand() → OnWorker() で Open2() を実行 → 処理完了後に Wait() から抜ける の順序を保証出来るようにしました。


v4.0.7での FreeLibrary() 時のフリーズも解消しているようです。
DllMain() でスレッドの同期をしてはいけないのは、マイクロソフトの開発者向けページでも明記されていますね。
https://learn.microsoft.com/ja-jp/windows/win32/dlls/dynamic-link-library-best-practices
解放処理用の関数をexportし、FreeLibrary() の前に呼ぶのは解決法として間違っていないと思います。

(9KB)

pagetop
タイトル
記事No
投稿日
投稿者
参照先
Re^2: kbGuru2SMF.kpi v0.02
258
2024/03/02(Sat) 11:45:17
Kobarin

> ただ、64bit版本体で起動直後の kbGuru2SMF.kpi の再生や、kbdmusic.kpi → kbGuru2SMF.kpi の切り替え後の再生が出来ないことが有りました。

検証ありがとうございます。
私も確認していて、手元の最新版では解決済みでした。原因となる箇所はご指摘の通りです。

後で気づきましたが FreeLibrary 時のフリーズは、スリープ時にデバイスを閉じるスレッドだけ
でなくて Port.cpp 内で作成したスレッドも関係してますね。

> 解放処理用の関数をexportし、FreeLibrary() の前に呼ぶのは解決法として間違っていないと思います。

何度考えても他に良いやり方が思いつきませんでした。
あえてやるなら、GGS4CloseDevice を呼ぶ度に内部で作成したインスタンスを破棄すること
でしょうか。そうすると GGS4CloseDevice を呼び出した後は GGS4GetSmfInformation 等の
結果も破棄されてしまうので、そうならないようにきちんと対応しようとすると結構大変
そうです。

VS2022 でビルドしたものだとフリーズは確認出来ないのですが、多分偶然だと思うのですよね。
API の新設以外に解決手段がないなら、公式版 GuruGuruSMF4.dll のパスを設定して使用出来る
ようにする現在の仕様は危険なのかもしれません。


手元の最新版では複数のインスタンスを同時に作成可能な作りにしてみました。
それ用の API を DLL に新設しなければなりませんが。

公式版があえてインスタンスを1つしか作らずに使い回すようにしてるのは、
デバイスを開く処理が何度も行われなくする為なのだろうとは思いますが、
ちょっと使い辛いんですよね。

インスタンスの使い回しは DLL を使う側で工夫してやれば良いかと思って。

でも苦労した割にほとんどメリットがないことが分かってしまいました。(笑)
64bit 版の本体から使う分には意味ないですし、32bit 版でも今の本体の仕様だと
やっぱりほとんど意味がないです。

演奏プラグイン仕様にフェードアウト用の API を追加するか本体が SetVolume を
駆使してフェードアウトを行ってクロスフェードに対応すれば 32bit 版でだけ意味
が出てくるかもしれないです。
pagetop
タイトル
記事No
投稿日
投稿者

Re^3: kbGuru2SMF.kpi v0.02
259
2024/03/03(Sun) 11:43:36
You
プラグインの設定で GuruGuruSMF4.dll のパスを指定できるのは、確かに安全とは言い切れませんね。
v4.0.7改とv4.0.6の両方のDLLを同梱して設定で選択できるようにする、ぐらいが良いかも知れません。
同梱しているDLLを上書きして公式版v4.0.7が呼ばれてしまう可能性は有りますが、それはさすがに自己責任でしょう。

GuruGuruSMF4.dll のシングルトンは意図が掴みかねますが、デバイスをオープンし直すのを嫌ったのは有り得そうです。
DLL内部にプレイリストを持つような仕様なども含め、イマイチ使い勝手が良くないところは有りますね。
ただ、演奏プラグインとしての機能は現状でも十分だと思いますし、
色々な改造をしてみるのは研究にとどめておくぐらいが良いかもしれません。

v4.0.6よりv4.0.7の方が再生開始まで微妙に時間がかかるのは、
v4.0.7がワーカースレッドで初期化処理するようになった影響でしょうか?(未調査です)
微妙に気になりますが、安定性とのトレードオフなら許容できる時間ではありますね。

※13:48追記
再生開始までの時間は、v4.0.7のソース GuruGuruSMF\Core\Ggs4Controller.cpp の
GgsController::Play() で1秒のウェイトが入っていたので気にしないでください。
pagetop
タイトル
記事No
投稿日
投稿者
参照先
Re^4: kbGuru2SMF.kpi v0.02
260
2024/03/03(Sun) 14:26:18
Kobarin

> ※13:48追記
> 再生開始までの時間は、v4.0.7のソース GuruGuruSMF\Core\Ggs4Controller.cpp の
> GgsController::Play() で1秒のウェイトが入っていたので気にしないでください。

デバイスを開き損なう件の回避の為なのかも、と思って手元の最新版ではウェイトを
入れないようにしていますが特に問題は確認出来ていません。

あとループ(無限ループ)が正しく機能していませんがこれは本体側の問題です。

本体が SetRepeat を呼んでくれないのもありますが、無視して無限ループしようとしても
うまくいきません。これはプラグイン側ではどう頑張っても対処出来ない問題でした。

本体の設定に応じたループ回数、フェード時間の SMF を本体が生成して、それが渡されてるので。
ループMIDI に非対応である筈のプラグインが、単曲リピートが無効なときには本体のループ回数と
フェード時間に対応してるかのように見えた動作をするのはその為です。

MIDI 対応演奏プラグインが今の本体の動作のままループに対応しようとしても、フェードアウトして
からループポイントに戻ってしまうので2ループ目は音が鳴らなくなります。そもそもフェードアウト
したら無限ループの意味がありません。

結構厄介でしたが手元の最新版では解決しています。少し強引で無駄がある方法で、きちんとやるには
少しだけプラグイン仕様の変更が必要となります。
pagetop
タイトル
記事No
投稿日
投稿者
参照先
ASIO が使えない
261
2024/03/03(Sun) 14:29:50
Kobarin

ASIO が使えなくなっていますね。

原因は本体が 3.12beta2 から COM の初期化を STA から MTA に変更したこと
のようです。STA に戻したら普通に動作しました。

kbviv.kpi の動作よりもっと重要な何かがあった気がしたのですが、敢えて
STA にしていたのはこの為だったのでしょう。

kbasio.kpi 側で対応するには少し大掛かりな修正が必要ですね。

どうしようかな…。
pagetop

- Web Forum v8.0 -
++ Edited by Hamel ++