soundplayer.playsyncは時期尚早に停止します
-
11-10-2019 - |
質問
GUIスレッドでWAVファイルを同期して再生したいのですが、PlaySyncへの呼び出しは早期に戻ってきます(そして、再生を早めに停止します)。 WAVファイルは2〜3分です。
これが私のコードのように見えるものです:
//in gui code (event handler)
//play first audio file
JE_SP.playSound("example1.wav");
//do a few other statements
doSomethingUnrelated();
//play another audio file
JE_SP.playSound("example2.wav");
//library method written by me, called in gui code, but located in another assembly
public static int playSound(string wavFile, bool synchronous = true,
bool debug = true, string logFile = "", int loadTimeout = FIVE_MINUTES_IN_MS)
{
SoundPlayer sp = new SoundPlayer();
sp.LoadTimeout = loadTimeout;
sp.SoundLocation = wavFile;
sp.Load();
switch (synchronous)
{
case true:
sp.PlaySync();
break;
case false:
sp.Play();
break;
}
if (debug)
{
string writeMe = "JE_SP: \r\n\tSoundLocation = " + sp.SoundLocation
+ "\r\n\t" + "Synchronous = " + synchronous.ToString();
JE_Log.logMessage(writeMe);
}
sp.Dispose();
sp = null;
return 0;
}
私が考えたことのいくつかは、ロードタイムアウトであり、別のスレッドでオーディオを再生し、GUIスレッドにサウンドファイルの期間を待つように強制することにより、GUIを手動で「フリーズ」します。ロードタイムアウトを延長しようとしましたが、それは何もしませんでした。
私/マイクロソフトではない誰かによって書かれたコードを使用せずに、WAVファイルの持続時間を取得する最良の方法が何であるかはよくわかりません。ファイルサイズを知っているため、これは計算できると思います。すべてのエンコードプロパティ(ビットレート、サンプルレート、サンプルサイズなど)は、再生する予定のすべてのファイルで一貫しています。この情報を使用してWAVファイルの期間を計算する方法について誰かが詳しく説明できますか?つまり、Playsyncが早期に戻ってくる理由について誰も考えていない場合です。
編集:
注:私は少し前にVB 6で同様の問題に遭遇しましたが、それはタイムアウトによって引き起こされましたが、ここでは問題であるとは思わない。短い(<1min)ファイルが正常に再生されるように見えるので、長いファイルを手動で編集してから、複数の呼び出しで個別に再生することにします。
追加情報:同じファイルが同時に一貫して停止していることに気付きました。ファイルはAudacityを使用して作成されました。 PlaySyncが、Audacityがプロデュースしたものとは異なるファイルの特定のエンコードを期待している可能性がありますか?
解決
他の誰かが大きなWAVファイルを同期して再生することに問題が発生した場合に備えて、ここにWMPを代替として使用する方法があります。
public static int playSoundWMP(string soundFile, bool synchronous = true)
{
Stopwatch sw = new Stopwatch();
sw.Start();
wmp.URL = soundFile;
wmp.controls.play();
Thread.Yield();
while (wmp.playState == WMPLib.WMPPlayState.wmppsTransitioning)
{
Application.DoEvents();
Thread.Yield();
}
int duration = Convert.ToInt32(wmp.currentMedia.duration * 1000);
double waitTime = wmp.currentMedia.duration;
if (synchronous)
{
Thread.Sleep(duration);
}
long elapsed = sw.ElapsedMilliseconds;
sw.Stop();
sw = null;
return (int) wmp.currentMedia.duration * 1000;
}
この方法では、WMPを使用してSoundPlayerクラスの代わりにオーディオファイルを再生するため、より大きなWAVファイルをより確実に再生できます...