2012-01-07 21 views
1

開発中のアプリケーションの一部で、ユーザーはマイクを使って何かを録音することができます。マイクから録音するには、Microphone Code sample by Microsoftのコードを使用しました。私はちょうどストリームにwavヘッダを書き込むためにコードを少し変更して、レコーディングを独立したストレージにwaveファイルとして保存できるようにしました。この後マイクからの録音とWindows Phoneでの再生

private void recordButton_Click(object sender, EventArgs e) 
     { 
      // Get audio data in 1/2 second chunks 
      microphone.BufferDuration = TimeSpan.FromMilliseconds(500); 

      // Allocate memory to hold the audio data 
      buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)]; 

      // Set the stream back to zero in case there is already something in it 
      stream.SetLength(0); 

      //Write wav header 
      WriteWavHeader(microphone.SampleRate); 

      // Start recording 
      microphone.Start(); 

      SetButtonStates(false, false, true,false); 
      UserHelp.Text = "record"; 
      StatusImage.Source = microphoneImage; 
      StatusImage.Visibility = System.Windows.Visibility.Visible; 
     } 

     public void WriteWavHeader(int sampleRate) 
     { 
      const int bitsPerSample = 16; 
      const int bytesPerSample = bitsPerSample/8; 
      var encoding = System.Text.Encoding.UTF8; 
      // ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form). 
      stream.Write(encoding.GetBytes("RIFF"), 0, 4); 

      // NOTE this will be filled in later 
      stream.Write(BitConverter.GetBytes(0), 0, 4); 

      // Format Contains the letters "WAVE"(0x57415645 big-endian form). 
      stream.Write(encoding.GetBytes("WAVE"), 0, 4); 

      // Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form). 
      stream.Write(encoding.GetBytes("fmt "), 0, 4); 

      // Subchunk1Size 16 for PCM. This is the size of therest of the Subchunk which follows this number. 
      stream.Write(BitConverter.GetBytes(16), 0, 4); 

      // AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression. 
      stream.Write(BitConverter.GetBytes((short)1), 0, 2); 

      // NumChannels Mono = 1, Stereo = 2, etc. 
      stream.Write(BitConverter.GetBytes((short)1), 0, 2); 

      // SampleRate 8000, 44100, etc. 
      stream.Write(BitConverter.GetBytes(sampleRate), 0, 4); 

      // ByteRate = SampleRate * NumChannels * BitsPerSample/8 
      stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4); 

      // BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels. 
      stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2); 

      // BitsPerSample 8 bits = 8, 16 bits = 16, etc. 
      stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2); 

      // Subchunk2ID Contains the letters "data" (0x64617461 big-endian form). 
      stream.Write(encoding.GetBytes("data"), 0, 4); 

      // NOTE to be filled in later 
      stream.Write(BitConverter.GetBytes(0), 0, 4); 
     } 

     public void UpdateWavHeader() 
     { 
      //if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header"); 

      var oldPos = stream.Position; 

      // ChunkSize 36 + SubChunk2Size 
      stream.Seek(4, SeekOrigin.Begin); 
      stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4); 

      // Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data. 
      stream.Seek(40, SeekOrigin.Begin); 
      stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4); 

      stream.Seek(oldPos, SeekOrigin.Begin); 
     } 

     private void stopButton_Click(object sender, EventArgs e) 
     { 
      if (microphone.State == MicrophoneState.Started) 
      { 
       // In RECORD mode, user clicked the 
       // stop button to end recording 
       microphone.Stop(); 
       UpdateWavHeader(); 
      } 
      else if (soundInstance.State == SoundState.Playing) 
      { 
       // In PLAY mode, user clicked the 
       // stop button to end playing back 
       soundInstance.Stop(); 
      } 

      SetButtonStates(true, true, false,true); 
      UserHelp.Text = "ready"; 
      StatusImage.Source = blankImage; 
     } 

ユーザーは、私は分離ストレージに保存記録を保存することchosesがあれば。

アプリケーションにはさまざまなページがあり、マイクを使用しているページがその1つです。このページへのナビゲーションが行われている別のページから行われます。今すぐ

NavigationService.Navigate(new Uri("/Mic.xaml", UriKind.Relative)); 

Mic.xamlページで、持つか、ユーザーが、彼は古いページに戻り、ハードウェアの戻るボタンをクリックした場合、何も記録せず。このページからMic.xamlページに再度移動して何かを記録しようとすると、記録されたファイルが正しく記録されないように見えます。録音に問題があるようです。

そこで、私たちは初めてのページに移動したときに記録が成功したが、我々は前後二回目のために移動したりするとき、それはしていません。

私がページを出るときにリソースをクリーンアップしないよう

答えて

4

Microsoftのサンプルは、複数ページのシナリオに適合していないエミュレータ上でテストを行っております。

まず、フィールドにDispatcherTimerを置く:

private DispatcherTimer dt; 

続いて、代わりに新しいDTを初期化するのは、このフィールドを使用するようにコンストラクタを変更します。

最後に
this.dt = new DispatcherTimer(); 

にOnNavigateFromメソッドをオーバーライドユーザーがページを離れるときを検出し、リソースをクリーンアップする:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) 
    { 
     base.OnNavigatedFrom(e); 

     dt.Stop(); 

     microphone.BufferReady -= this.microphone_BufferReady; 
    } 
+0

ありがとうrkedのような魅力 – Saurabh

関連する問題