2016-12-14 228 views
0

NAudioを使ってwaveファイルに記録して書き込むために、次の2つの関数を書きました。最後の行を実行せずに、ローカルスコープから出ることなく、最初の機能を停止するための戦術を見つけることができません。NAudioで音声を録音し、マイク入力が無音になったときにファイルに書き込む

audio_Rec方法は、メイン関数から呼び出されWaveInEventにバッファリングされたデータがある場合audioSource_DataAvailable機能が実行されます。私が思うとおり、audioSource_DataAvailable機能はaudio_Rec法の範囲内でのみ実行され、コードは(行以下)audio_Recの最後の行に来るとき、

Console.Write("Recording Starts...\n"); 

それはスコープの外に出ると、 main関数の次の行が実行されます。 (主な記載はありません)です。私はaudioSource_DataAvailable関数で指定された条件で録音が停止するまでオーディオを録音しながら、audio_Recメソッドを保持するメソッドを必要とします。

合計は、パブリックメンバ変数です。

audio_Rec方法

public void audio_Rec() 
    { 
     audioSource = new WaveInEvent(); 
     audioSource.DeviceNumber = 0; 
     audioSource.WaveFormat = new WaveFormat(16000, 16, 1); 

     audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable); 
     waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat); 

     audioSource.StartRecording(); 
     Console.Write("Recording Starts...\n"); 

     //Thread.Sleep(7000); 
    } 

audioSource_DataAvailable機能

void audioSource_DataAvailable(object sender, WaveInEventArgs e) 
    { 
     count++; 
     if (count%5 == 0) 
     { 
      if (summation < 150000) { 
       audioSource.StopRecording(); 
       Console.Write("Recording Stopped!"); 
      } 
      Console.WriteLine(count * 100 + "ms :"+summation); 
      summation = 0; 
     } 

     Console.WriteLine(count+" "+summation); 
     byte[] buf = new byte[e.BytesRecorded]; 
     buf = e.Buffer; 
     int[] Ints = new int[e.BytesRecorded/2]; 

     for(int i=0;i<buf.Length;i+=2) 
     { 
      Ints[i/2] = BitConverter.ToInt16(buf, i); 
     } 

     int[] newInts = Ints.Select(x => Math.Abs(x)).ToArray(); 
     summation = newInts.Sum(); 

     if (waveFile != null) 
     { 
      waveFile.Write(e.Buffer, 0, e.BytesRecorded); 
      waveFile.Flush(); 
     } 
    } 

第二の機能でアルゴリズムを無視する自由。彼らは無視することができます。 ご協力いただきまして誠にありがとうございます。おかげ

答えて

0

あなたは次のことを試すことができます。

  • はNAudio波デバイスからRecordingStoppedイベントを処理します。
  • EventまたはSemaphoreまたはその他の同期プリミティブをクラスレベルで作成します。
  • RecordingStoppedハンドラがトリガされると、同期プリミティブをキックします。
  • メインメソッドを終了する前に、そのプリミティブでWaitOne()を実行してください。

それが終了することができるように、あなたのメインスレッドをウェイクアップセマフォを、トリガーStoppedハンドラの呼び出しでDataAvailableハンドラ結果であなたのStopRecordingコール。

例(それは私が使用しているものですので、私は、セマフォの部分です):

using System.Threading; 

Semaphore AudioSync = new Semaphore(0, int.MaxValue); 

public void audio_Rec() 
{ 
    audioSource = new WaveInEvent(); 
    audioSource.DeviceNumber = 0; 
    audioSource.WaveFormat = new WaveFormat(16000, 16, 1); 

    // Register for the 'RecordingStopped' event. 
    audioSource.PlaybackStopped += this.audioSource_PlaybackStopped; 

    audioSource.DataAvailable += new EventHandler<WaveInEventArgs>(audioSource_DataAvailable); 
    waveFile = new WaveFileWriter(@"d:/dev/csharp/wspeechrec/new_wave.wav", audioSource.WaveFormat); 

    audioSource.StartRecording(); 
    Console.Write("Recording Starts...\n"); 

    // Now just wait for the "PlaybackStopped" event handler to signal completion. 
    AudioSync.WaitOne(); // <------------------------------------- 
} 

Stoppedイベントハンドラ:助けを

void audioSource_PlaybackStopped(object sender, StoppedEventArgs e) 
{ 
    // Wakes up the main thread. 
    AudioSync.Release(); 
} 
+0

感謝。私はwhileループを使って方法を見つけました。私は、最後の行(Console.Write( "Recording Starts ... \ n");)の最後にwhile(!flag)ループを追加して、 "flag == true?"を継続的にチェックします。そして、 "記録停止"の後に "flag = true"を追加しました。今はスムーズに動作します。 –

関連する問題