zoukankan      html  css  js  c++  java
  • 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 下载。其效果图如下所示:

  • 相关阅读:
    【IDEA】(4)---很好用的DEBUG功能
    【IDEA】(3)---非常实用提高开发效率和水平的插件
    【IDEA】(2)---MAC代码模版
    【IDEA】(1)---MAC下常用快捷键
    Shell(2)—数组
    MySQL(12)---纪录一次left join一对多关系而引起的BUG
    MySQL(11)---约束
    Shell(1)---变量
    算法(2)---算法复杂度理论
    MySQL(10)---自定义函数
  • 原文地址:https://www.cnblogs.com/chengxingliang/p/2046981.html
Copyright © 2011-2022 走看看