Silverlight实用窍门系列:41.Silverlight中调用麦克风模拟录音机设备,存储为WAV音频【附带实例源码】

        在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 下载。其效果图如下所示:

Silverlight实用窍门系列:41.Silverlight中调用麦克风模拟录音机设备,存储为WAV音频【附带实例源码】_第1张图片

你可能感兴趣的:(silverlight)