2

私はnaudioを使用してオーディオプログラミングを行っています(チュートリアルを使用)。私のプログラム(C#.net winForms)には、記録と停止のボタンがあります。コードは次のようになります。

    NAudio.Wave.WaveIn sourceStream = null;
    NAudio.Wave.WaveFileWriter waveWriter = null;

    private void RecordButton_Click(object sender, EventArgs e)
    {
        int deviceNumber = 0;
        sourceStream = new NAudio.Wave.WaveIn();
        sourceStream.DeviceNumber = deviceNumber;
        sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);

        sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
        waveWriter = new NAudio.Wave.WaveFileWriter("d:\\a.wav", sourceStream.WaveFormat);

        sourceStream.StartRecording();
    }

    private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
    {
        if (waveWriter == null) return;

        waveWriter.WriteData(e.Buffer, 0, e.BytesRecorded);
        waveWriter.Flush();
    }

    private void StopButton_Click(object sender, EventArgs e)
    { 
            waveWriter.Dispose();
            waveWriter = null;       
    }

それは動作しますが、ウェーブファイルの品質は良くありません-私が録音したサウンドには小さなギャップがあります。サンプルレート44100Hzとサンプルフォーマット16ビットが必要です。

4

2 に答える 2

1

あなたが見つけたものを正確に再現することはできませんでしたが、DataAvailableイベントが他の操作のためにブロックされる余地があまりないことに気付きました. 単純Thread.Sleep(100);にアプリケーションを停止します。

継続的な書き込み (およびフラッシュ) が問題に寄与している可能性があると仮定すると、Queue書き込まれるバイトを保持し、スレッドプールのスレッドを使用して実際の書き込みを行う単純な方法を実装しました。

イベントは次のDataAvailableようになります。

    Queue<byte[]> writebuffer = new Queue<byte[]>();

    private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
    {
        if (waveWriter == null) return;

        byte[] realbytes = new byte[e.BytesRecorded];
        Array.Copy(e.Buffer, realbytes, e.BytesRecorded);
        writebuffer.Enqueue(realbytes);
    }

呼び出しの直後に、StartRecordingキューを読み取ってデータをストリームに書き込むタスクをキューに入れます。そこに遅延を追加すると、アプリケーションは停止しなくなります。

ThreadPool.QueueUserWorkItem((s) =>
{
    var keeprunning = true;
    sourceStream.RecordingStopped += (rss, rse) => { keeprunning = false; };
    while(keeprunning)
    {
        if (writebuffer.Count==0)
        {
                Thread.Sleep(0);
        }
        else
        { 
            var buf = writebuffer.Dequeue();
            waveWriter.Write(buf,0,buf.Length);
            // Thread.Sleep(100); // for testing 
        }
    }
    waveWriter.Dispose();
    waveWriter = null;
});
于 2016-05-07T18:16:18.393 に答える