在Silverlight 4中支持了麦克风设置的调用,在本节中我们将调用麦克风设备,然后进行录音,并且将录制的声音存取为Wav音频文件。
第一步、首先我们从AudioSink类派生一个音频接收器类:WavAudioSink。其代码如下所示:
- public class WavAudioSink:AudioSink
- {
- // 设置需要记录的内存流
- private MemoryStream _stream;
- // 设置当前的音频格式
- private AudioFormat _format;
- public Stream BackingStream
- {
- get { return _stream; }
- }
- public AudioFormat CurrentFormat
- {
- get { return _format; }
- }
- protected override void OnCaptureStarted()
- {
- _stream = new MemoryStream(1024);
- }
- protected override void OnCaptureStopped()
- {
- }
- protected override void OnFormatChange(AudioFormat audioFormat)
- {
- if (audioFormat.WaveFormat != WaveFormatType.Pcm)
- throw new InvalidOperationException("WavAudioSink只支持PCM音频格式");
- _format = audioFormat;
- }
- protected override void OnSamples(long sampleTime, long sampleDuration,
- byte[] sampleData)
- {
- // 新的音频数据到达,将它们写入流
- _stream.Write(sampleData, 0, sampleData.Length);
- }
- }
第二步、然后我们将编写一个保存音频的函数类,以保存读取到的音频数据:
- public class SaveWAVHelper
- {
- public static void SavePcmToWav(Stream rawData, Stream output, AudioFormat audioFormat)
- {
- if (audioFormat.WaveFormat != WaveFormatType.Pcm)
- throw new ArgumentException("Only PCM coding is supported.");
- BinaryWriter bwOutput = new BinaryWriter(output);
- // -- RIFF 块
- bwOutput.Write("RIFF".ToCharArray());
- // 包的总长度
- // 计算的数据长度加上数据头的长度没有数据
- // 写数据(44 - 4 ("RIFF") - 4 (当前数据))
- bwOutput.Write((uint)(rawData.Length + 36));
- bwOutput.Write("WAVE".ToCharArray());
- // -- FORMAT 块
- bwOutput.Write("fmt ".ToCharArray());
- // FORMAT 块的长度 (Binary, 总是 0x10)
- bwOutput.Write((uint)0x10);
- // 总是 0x01
- bwOutput.Write((ushort)0x01);
- // 通道数( 0x01=单声道, 0x02=立体声)
- bwOutput.Write((ushort)audioFormat.Channels);
- // 采样率 (Binary, Hz为单位)
- bwOutput.Write((uint)audioFormat.SamplesPerSecond);
- // 字节每秒
- bwOutput.Write((uint)(audioFormat.BitsPerSample * audioFormat.SamplesPerSecond *
- audioFormat.Channels / 8));
- // 每个样品字节: 1=8 bit 单声道, 2=8 bit 立体声 or 16 bit 单声道, 4=16 bit 立体声
- bwOutput.Write((ushort)(audioFormat.BitsPerSample * audioFormat.Channels / 8));
- // 每个样品字节
- bwOutput.Write((ushort)audioFormat.BitsPerSample);
- // -- DATA 块
- bwOutput.Write("data".ToCharArray());
- // DATA数据块的长度
- bwOutput.Write((uint)rawData.Length);
- // 原始PCM数据如下
- // 复位rawData地位,记住它的原点位置
- // 恢复底。
- long originalRawDataStreamPosition = rawData.Position;
- rawData.Seek(0, SeekOrigin.Begin);
- //追加到输出流中的所有数据从rawData流
- byte[] buffer = new byte[4096];
- int read;
- // 循环读取字节数据
- while ((read = rawData.Read(buffer, 0, 4096)) > 0)
- {
- bwOutput.Write(buffer, 0, read);
- }
- //开始写入数据
- rawData.Seek(originalRawDataStreamPosition, SeekOrigin.Begin);
- }
- }
第三步、然后再MainPage.xaml中我们添加三个按钮,分别是开始记录音频、停止录制音频、保存音频文件三个按钮。
- <Grid x:Name="LayoutRoot" Background="White">
- <Button Content="开始录制" Height="28" HorizontalAlignment="Left"
- Margin="30,15,0,0" Name="btnRecord" VerticalAlignment="Top"
- Width="71" Click="btnRecord_Click" />
- <Button Content="停止录制" Height="28" HorizontalAlignment="Left"
- Margin="150,15,0,0" Name="btnStopRecord" VerticalAlignment="Top"
- Width="71" Click="btnStopRecord_Click" />
- <Button Content="保存音频" Height="28" HorizontalAlignment="Left"
- Margin="268,15,0,0" Name="btnSaveWav" VerticalAlignment="Top"
- Width="71" Click="btnSaveWav_Click" />
- </Grid>
第四步、最后在MainPage.xaml.cs代码中我们进行录制、停止、保存音频的操作如下所示:
- public partial class MainPage : UserControl
- {
- public MainPage()
- {
- InitializeComponent();
- btnRecord.IsEnabled = true;
- btnStopRecord.IsEnabled = false;
- btnSaveWav.IsEnabled = false;
- }
- //声明私有变量
- private WavAudioSink _wavSink;
- private CaptureSource _captureSource;
- private SaveFileDialog _saveFileDialog = new SaveFileDialog()
- { Filter = "Audio files (*.wav)|*.wav" };
- private void btnRecord_Click(object sender, RoutedEventArgs e)
- {
- //初始化_captureSource
- var audioDevice = CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice();
- _captureSource = new CaptureSource() { AudioCaptureDevice = audioDevice };
- //有默认设置的设备且可以用来录制音频
- if (CaptureDeviceConfiguration.AllowedDeviceAccess ||
- CaptureDeviceConfiguration.RequestDeviceAccess())
- {
- //判断当前没有开始录制音频
- if (_captureSource.State == CaptureState.Stopped)
- {
- //初始化WavAudioSink
- _wavSink = new WavAudioSink();
- _wavSink.CaptureSource = _captureSource;
- //开始录制音频
- _captureSource.Start();
- }
- }
- btnRecord.IsEnabled = false;
- btnStopRecord.IsEnabled = true;
- btnSaveWav.IsEnabled = false;
- }
- private void btnStopRecord_Click(object sender, RoutedEventArgs e)
- {
- //如果当前状态为开始录制,则停止录制
- if (_captureSource.State == CaptureState.Started)
- {
- _captureSource.Stop();
- }
- btnRecord.IsEnabled = false;
- btnStopRecord.IsEnabled = false;
- btnSaveWav.IsEnabled = true;
- }
- private void btnSaveWav_Click(object sender, RoutedEventArgs e)
- {
- if (_saveFileDialog.ShowDialog() == false)
- {
- return;
- }
- //保存Wav文件
- Stream stream = _saveFileDialog.OpenFile();
- SaveWAVHelper.SavePcmToWav(_wavSink.BackingStream, stream, _wavSink.CurrentFormat);
- stream.Close();
- MessageBox.Show("你的音频已经保存");
- btnRecord.IsEnabled = true;
- btnStopRecord.IsEnabled = false;
- btnSaveWav.IsEnabled = false;
- }
- }
通过以上步骤我们就可以开始调用麦克风录制音频文件了,本实例采用Silverlight 4.0+VS2010编写,如需源码请点击 SL4Audio.zip 下载。其效果图如下所示:
本文转自程兴亮 51CTO博客,原文链接:http://blog.51cto.com/chengxingliang/826448