天天看點

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) 

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