在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)
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;
private void btnStopRecord_Click(object sender, RoutedEventArgs e)
//如果目前狀态為開始錄制,則停止錄制
if (_captureSource.State == CaptureState.Started)
_captureSource.Stop();
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("你的音頻已經儲存");
<a target="_blank" href="http://blog.51cto.com/attachment/201204/222552585.jpg"></a>
本文轉自程興亮 51CTO部落格,原文連結:http://blog.51cto.com/chengxingliang/826448