Win32APIのPlaySoundの非同期再生と、ガベージコレクションについて。

タグの編集
投稿者 bz9  (中学生) 投稿日時 2013/6/7 21:49:58
WaveファイルをByte配列として読み込んで、
PlaySound関数に渡して非同期再生させようと思っているのですが、
ノイズのような音が再生されるだけで、正しく再生されません。
同期再生なら成功したので、ファイル自体は壊れていたりしないと思うのですが・・・

いろいろ調べた結果、ガベージコレクション機能が邪魔をしていたみたいなので、
DOBON.NET さんのコードを参考にコードを書いてみても、ノイズ・・・
そのコードをコピーしてもノイズが再生されてしまって困っています。

http://dobon.net/vb/dotnet/programing/playembeddedwave.html#asyncbug

環境はWindows7 HomePremium 64Bit、VB2010、.NET Framework 2.0 と、 4 Client Profileで試しました。

どうすれば 正しく再生されますか。
投稿者 るきお  (社会人) 投稿日時 2013/6/8 19:13:27
検証したうえでの回答ではありません。

PlaySoundではなく、mciSendStringを使うとどうでしょうか?
サンプルはこちらで紹介しています。

サウンドを再生する
http://homepage1.nifty.com/rucio/main/dotnet/Samples/Sample060Playmp3.htm

Visual Basic サンプル集
http://homepage1.nifty.com/rucio/main/dotnet/Samples/SmpleCnt.htm
投稿者 YuO  (社会人) 投稿日時 2013/6/8 23:05:17
GCが原因なら,Marshal.AllocHGlbalでアンマネージドメモリを割り当てれば済みそうな気がしますが……。
# るきおさんと同じく検証したわけではありませんが。

[MSDN] Marshal.AllocHGlobal
http://msdn.microsoft.com/ja-jp/library/s69bkh17.aspx
[MSDN] Marshal.Copy
http://msdn.microsoft.com/ja-jp/library/ms146625.aspx
[MSDN] Marshal.FreeHGlobal
http://msdn.microsoft.com/ja-jp/library/system.runtime.interopservices.marshal.freehglobal.aspx
投稿者 bz9  (中学生) 投稿日時 2013/6/9 09:37:15
> GCが原因なら,Marshal.AllocHGlbalでアンマネージドメモリを割り当てれば済みそうな気がしますが……。

あれ、これ使ってもノイズが鳴っちゃうってことは、もしかしてGCが原因じゃなかったのか・・?
Dim Addr As IntPtr = IntPtr.Zero
Sub Wave(ByVal Data As Byte())
    Marshal.FreeHGlobal(Addr)
    Addr = Marshal.AllocHGlobal(Data.Length)
    Marshal.Copy(Data, 0, Addr, Data.Length)
    PlaySound(Addr, IntPtr.Zero, SND_ASYNC Or SND_MEMORY)
End Sub

これで呼び出してみているんですが、やっぱりノイズみたいなのがなっちゃいます。

一応どんな感じの音がなるのか録音してみました。

正常ななり方:http://sites.google.com/site/bz9okiba/Test.wav
ノイズ?:http://sites.google.com/site/bz9okiba/noise.wav


> PlaySoundではなく、mciSendStringを使うとどうでしょうか?

るきおさんのサンプルのファイル名だけ書き換えて実行したら、正しく再生されました。

mciSendStringで再生できたので解決にします。


ただ、何でPlaySound関数だと成功しないのかが気になります・・・・