且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Silverlight实用系列:41.Silverlight中调用麦克风模拟录音机设备,存储为WAV音频

更新时间:2022-10-04 16:23:50

      在Silverlight 4中支持了麦克风设置的调用,在本节中我们将调用麦克风设备,然后进行录音,并且将录制的声音存取为Wav音频文件。

        第一步、首先我们从AudioSink类派生一个音频接收器类:WavAudioSink。其代码如下所示:


  1. public class WavAudioSink:AudioSink 
  2. // 设置需要记录的内存流 
  3. private MemoryStream _stream; 
  4. // 设置当前的音频格式 
  5. private AudioFormat _format; 
  6.  
  7. public Stream BackingStream 
  8. get { return _stream; } 
  9.  
  10. public AudioFormat CurrentFormat 
  11. get { return _format; } 
  12.  
  13. protected override void OnCaptureStarted() 
  14. _stream = new MemoryStream(1024); 
  15.  
  16. protected override void OnCaptureStopped() 
  17.  
  18. protected override void OnFormatChange(AudioFormat audioFormat) 
  19. if (audioFormat.WaveFormat != WaveFormatType.Pcm) 
  20. throw new InvalidOperationException("WavAudioSink只支持PCM音频格式"); 
  21.  
  22. _format = audioFormat; 
  23.  
  24. protected override void OnSamples(long sampleTime, long sampleDuration, 
  25. byte[] sampleData) 
  26. // 新的音频数据到达,将它们写入流 
  27. _stream.Write(sampleData, 0, sampleData.Length); 

        第二步、然后我们将编写一个保存音频的函数类,以保存读取到的音频数据:


  1. public class SaveWAVHelper 
  2. public static void SavePcmToWav(Stream rawData, Stream output, AudioFormat audioFormat) 
  3. if (audioFormat.WaveFormat != WaveFormatType.Pcm) 
  4. throw new ArgumentException("Only PCM coding is supported."); 
  5.  
  6. BinaryWriter bwOutput = new BinaryWriter(output); 
  7.  
  8. // -- RIFF 块 
  9. bwOutput.Write("RIFF".ToCharArray()); 
  10. // 包的总长度 
  11. // 计算的数据长度加上数据头的长度没有数据 
  12. // 写数据(44 - 4 ("RIFF") - 4 (当前数据)) 
  13. bwOutput.Write((uint)(rawData.Length + 36)); 
  14. bwOutput.Write("WAVE".ToCharArray()); 
  15.  
  16. // -- FORMAT 块 
  17. bwOutput.Write("fmt ".ToCharArray()); 
  18. // FORMAT 块的长度 (Binary, 总是 0x10) 
  19. bwOutput.Write((uint)0x10); 
  20. // 总是 0x01 
  21. bwOutput.Write((ushort)0x01); 
  22. // 通道数( 0x01=单声道, 0x02=立体声) 
  23. bwOutput.Write((ushort)audioFormat.Channels); 
  24. // 采样率 (Binary, Hz为单位) 
  25. bwOutput.Write((uint)audioFormat.SamplesPerSecond); 
  26. // 字节每秒 
  27. bwOutput.Write((uint)(audioFormat.BitsPerSample * audioFormat.SamplesPerSecond * 
  28. audioFormat.Channels / 8)); 
  29. // 每个样品字节: 1=8 bit 单声道, 2=8 bit 立体声 or 16 bit 单声道, 4=16 bit 立体声 
  30. bwOutput.Write((ushort)(audioFormat.BitsPerSample * audioFormat.Channels / 8)); 
  31. // 每个样品字节 
  32. bwOutput.Write((ushort)audioFormat.BitsPerSample); 
  33.  
  34. // -- DATA 块 
  35. bwOutput.Write("data".ToCharArray()); 
  36. // DATA数据块的长度 
  37. bwOutput.Write((uint)rawData.Length); 
  38. // 原始PCM数据如下 
  39. // 复位rawData地位,记住它的原点位置 
  40. // 恢复底。 
  41. long originalRawDataStreamPosition = rawData.Position; 
  42. rawData.Seek(0, SeekOrigin.Begin); 
  43. //追加到输出流中的所有数据从rawData流 
  44. byte[] buffer = new byte[4096]; 
  45. int read
  46. // 循环读取字节数据 
  47. while ((read = rawData.Read(buffer, 0, 4096)) > 0) 
  48. bwOutput.Write(buffer, 0, read); 
  49. //开始写入数据 
  50. rawData.Seek(originalRawDataStreamPosition, SeekOrigin.Begin); 

        第三步、然后再MainPage.xaml中我们添加三个按钮,分别是开始记录音频、停止录制音频、保存音频文件三个按钮。


  1. <Grid x:Name="LayoutRoot" Background="White"
  2. <Button Content="开始录制" Height="28" HorizontalAlignment="Left" 
  3. Margin="30,15,0,0" Name="btnRecord" VerticalAlignment="Top" 
  4. Width="71" Click="btnRecord_Click" /> 
  5. <Button Content="停止录制" Height="28" HorizontalAlignment="Left" 
  6. Margin="150,15,0,0" Name="btnStopRecord" VerticalAlignment="Top" 
  7. Width="71" Click="btnStopRecord_Click" /> 
  8. <Button Content="保存音频" Height="28" HorizontalAlignment="Left" 
  9. Margin="268,15,0,0" Name="btnSaveWav" VerticalAlignment="Top" 
  10. Width="71" Click="btnSaveWav_Click" /> 
  11. </Grid> 

        第四步、最后在MainPage.xaml.cs代码中我们进行录制、停止、保存音频的操作如下所示:


  1. public partial class MainPage : UserControl 
  2. public MainPage() 
  3. InitializeComponent(); 
  4.  
  5. btnRecord.IsEnabled = true
  6. btnStopRecord.IsEnabled = false
  7. btnSaveWav.IsEnabled = false
  8.  
  9. //声明私有变量 
  10. private WavAudioSink _wavSink; 
  11. private CaptureSource _captureSource; 
  12. private SaveFileDialog _saveFileDialog = new SaveFileDialog() 
  13. { Filter = "Audio files (*.wav)|*.wav" }; 
  14.  
  15. private void btnRecord_Click(object sender, RoutedEventArgs e) 
  16.  
  17. //初始化_captureSource 
  18. var audioDevice = CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice(); 
  19. _captureSource = new CaptureSource() { AudioCaptureDevice = audioDevice }; 
  20.  
  21. //有默认设置的设备且可以用来录制音频 
  22. if (CaptureDeviceConfiguration.AllowedDeviceAccess || 
  23. CaptureDeviceConfiguration.RequestDeviceAccess()) 
  24. //判断当前没有开始录制音频 
  25. if (_captureSource.State == CaptureState.Stopped) 
  26. //初始化WavAudioSink 
  27. _wavSink = new WavAudioSink(); 
  28. _wavSink.CaptureSource = _captureSource; 
  29. //开始录制音频 
  30. _captureSource.Start(); 
  31.  
  32.  
  33. btnRecord.IsEnabled = false
  34. btnStopRecord.IsEnabled = true
  35. btnSaveWav.IsEnabled = false
  36.  
  37. private void btnStopRecord_Click(object sender, RoutedEventArgs e) 
  38. //如果当前状态为开始录制,则停止录制 
  39. if (_captureSource.State == CaptureState.Started) 
  40. _captureSource.Stop(); 
  41.  
  42. btnRecord.IsEnabled = false
  43. btnStopRecord.IsEnabled = false
  44. btnSaveWav.IsEnabled = true
  45.  
  46. private void btnSaveWav_Click(object sender, RoutedEventArgs e) 
  47. if (_saveFileDialog.ShowDialog() == false
  48. return
  49. //保存Wav文件 
  50. Stream stream = _saveFileDialog.OpenFile(); 
  51. SaveWAVHelper.SavePcmToWav(_wavSink.BackingStream, stream, _wavSink.CurrentFormat); 
  52.  
  53. stream.Close(); 
  54.  
  55. MessageBox.Show("你的音频已经保存"); 
  56.  
  57. btnRecord.IsEnabled = true
  58. btnStopRecord.IsEnabled = false
  59. btnSaveWav.IsEnabled = false

        通过以上步骤我们就可以开始调用麦克风录制音频文件了,本实例采用Silverlight 4.0+VS2010编写,如需源码请点击 SL4Audio.zip 下载。其效果图如下所示:

 

Silverlight实用系列:41.Silverlight中调用麦克风模拟录音机设备,存储为WAV音频



本文转自程兴亮 51CTO博客,原文链接:http://blog.51cto.com/chengxingliang/826448