2009-04-02 15 views
0

生のオーディオストリームを録音して再生する目的でWaveOutとWaveInクラスを公開するWinMMライブラリラッパーライブラリを作成しました。WinMMライブラリの問題

すべてがうまくいきますが、完成したバッファを処理する方法に関するオペレーティングシステムの仕様に従うために、バッファを準備してメモリを解放するスレッドを追加しました。また、すべての同期がダウンしているので、クラスは確実にスレッドセーフです。

しかし、WaveOutデバイスにバッファを追加してオペレーティングシステムが成功コードを返すという稀な問題があるようですが、デバイスが直後にリセットされた場合、OSはバッファを完了したものとしてマークしません。それをアプリケーションに戻します。

バッファを失っているようです。だから問題は、デバイスに送信された個々のバッファの数を追跡し、それらをクリーンアップするスレッドにClose()関数を参加させないことです。

アイデア、または既知のバグはありますか?

PS:これはVistaのクアッドコアでは起こりそうにないが、XPプロのデュアルコアで起こる。

EDIT1:完全なソースコードを公開していただき、誰かを助けることができれば、コードプレックスでライセンスを取得していただきます。

EDIT2:CodePlexのに掲示されるライブラリ:http://winmm.codeplex.com/

ここでは、問題の原因かのアイデアです:

public partial class MainView : Form 
{ 
    private WaveIn waveIn = new WaveIn(WaveIn.WaveInMapperDeviceId); 
    private WaveOut waveOut = new WaveOut(WaveOut.WaveOutMapperDeviceId); 

    public MainView() 
    { 
     InitializeComponent(); 

     WaveFormat format = WaveFormat.Pcm44Khz16BitMono; 

     waveOut.Open(format); 

     waveIn.DataReady += new EventHandler<DataReadyEventArgs>(WaveIn_DataReady); 

     // Tweaking these values affects the internal buffering thread. 
     // Setting too small of a QueueSize with too small of a BufferSize 
     // will cause buffer underruns, which will sound like choppy audio. 
     waveIn.BufferQueueSize = 200; 
     waveIn.BufferSize = 64; 

     waveIn.Open(format); 

     waveIn.Start(); 
    } 

    void WaveIn_DataReady(object sender, DataReadyEventArgs e) 
    { 
     if (waveOut != null) 
     { 
      lock (waveOut) 
      { 
       // We have to check for null after the lock, 
       // because waveOut may have been disposed 
       // inside another lock. 
       if (waveOut != null) 
       { 
        waveOut.Write(e.Data); 
       } 
      } 
     } 
    } 

    private void MainView_FormClosed(object sender, FormClosedEventArgs e) 
    { 
     if (waveIn != null) 
     { 
      lock (waveIn) 
      { 
       waveIn.Dispose(); 
       waveIn = null; 
      } 
     } 

     if (waveOut != null) 
     { 
      lock (waveOut) 
      { 
       waveOut.Dispose(); 
       waveOut = null; 
      } 
     } 
    } 
} 

答えて

1

私が最初にロックする上で別のobjectを作成します。これは、ヌルチェックロジックを単純化するはずです(ロックの前後でチェックしてから約半分)。

第2に、Disposeは変数をnullに設定しないため、オブジェクトがnullでなく廃棄されるため、他のチェックは引き続き通過します。だから私はそうするだろう

waveOut.Dispose(); 
waveout = null; 

明示的にnullに設定されていることを確認してください。

+0

ああ、別のオブジェクトに良いアイデア。 また、私が問題に取り組んでいた実際のアプリでは、私はexplicetly nullに設定していました。 –

+0

少なくとも建設的なフィードバックをいただいたので、問題が解決されているかどうか分からないにもかかわらず、奨励金をお渡しします。 –

関連する問題