第一篇windows phone 7博客:windows phone 7 上编写录音软件全纪录

申请这个csdn账号已经很久了,申请的时候是为了下载资源,,,越来越发现这个网站的强大,各种大牛啊!

我经常在百度里面搜资源,一点进去才发现搜到的博客或帖子是csdn的!近来做了点事(当然是最初级的,不敢跟大牛们相比),贴出来,供和我一样的freshman们做参考。


闲话少叙:最近实验室有个项目是基于windows phone 7的,利用wp7手机的音频口将单片机节点采集的数据收集起来,也就是用音频口和单片机通信。上网查也查不到资源,只能按部就班从wp7入手,看看wp7是怎么处理音频的。后来在MSDN上搜到了一个很好的麦克风的例子(在酷乐或风暴数码下载到的录音机软件估计也就是这么编出来的吧。。。难道是我的三星focus与开发者的不兼容?我下载了好几个xap才下到一个好使的!)

先声明:我下面将写的内容是根据msdn上的样例写的,基本算是抄袭吧,不过有自己学习消化的过程。

这是msdn上代码的下载地址:http://msdn.microsoft.com/zh-cn/library/ff431744(v=VS.92).aspx


如果安装好了wp7的sdk,就可以打开这个工程。

(有的例子下载下来出现错误,silverlightversion不对什么的。但是这个microphone的却可以打开。。。)

先看看界面是啥样的:


其xaml文件内容:

<phone:PhoneApplicationPage 
    x:Class="SilverlightMicrophoneSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="MainPanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="toddhan_MICROPHONE SAMPLE" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="UserHelp" Text="press record" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" Height="200" />
        </StackPanel>
        <Image x:Name="StatusImage" Grid.Row="1" Height="334" Width="366" 
               HorizontalAlignment="Center" VerticalAlignment="Center"
               Source="Images/blank.png" Margin="61,0,53,97" />
        <!--ContentPanel - place additional content here-->
    </Grid>

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBar.Buttons>
                <shell:ApplicationBarIconButton x:Name="recordButton" Text="record" IconUri="/Images/record.png" Click="recordButton_Click" IsEnabled="True"/>
                <shell:ApplicationBarIconButton x:Name="playButton" Text="play" IconUri="/Images/play.png" Click="playButton_Click" IsEnabled="False"/>
                <shell:ApplicationBarIconButton x:Name="stopButton" Text="stop" IconUri="/Images/stop.png" Click="stopButton_Click" IsEnabled="False"/>
            </shell:ApplicationBar.Buttons>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

</phone:PhoneApplicationPage>

1、其中的playsongs是我自己起的文件的名字。

2、之前学了一些wp7中简单的控件、事件操作,但还没写过applicationBar,这个地方用到了这个东西!

3、其中按钮配的图片都在solution的Images文件夹中。

下面是C#程序:

using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace playingsongs
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Microphone microphone = Microphone.Default;
        private byte[] buffer;//获取音频的缓冲区
        private MemoryStream stream = new MemoryStream();//存放数据
        private SoundEffectInstance soundInstance;
        private bool soundIsPlaying = false;

        //图片设置(只是在xaml里面这是不行的。还要对图片进行设置)
        private BitmapImage blankImage;
        private BitmapImage microphoneImage;
        private BitmapImage speakerImage;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            //这个timer模拟XNA中的游戏循环,microphone是基于XNA的,也是用这个timer来监视音频回放的状态以更新UI元素
            DispatcherTimer dt = new DispatcherTimer();
            dt.Interval = TimeSpan.FromMilliseconds(33);
            dt.Tick += new EventHandler(dt_Tick);
            dt.Start();

            microphone.BufferReady += new EventHandler<EventArgs>(microphone_BufferReady);
            blankImage = new BitmapImage(new Uri("Image/blank.png", UriKind.RelativeOrAbsolute));
            microphoneImage = new BitmapImage(new Uri("Image/microphone.png", UriKind.RelativeOrAbsolute));
            speakerImage = new BitmapImage(new Uri("Image/speaker.png", UriKind.RelativeOrAbsolute));
        }
        /// <summary>
        /// 更新xna定时器分配,检查是否有音乐正在播放
        /// 如果声音已经停止播放,将更新UI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void dt_Tick(object sender, EventArgs e)
        {
            try
            {
                FrameworkDispatcher.Update();
            }
            catch { }
            if (soundIsPlaying == true)
            {
                if (soundInstance.State != SoundState.Playing)
                {
                    soundIsPlaying = false;//播放已经停止
                    //既然已经播放完毕,要更新UI中的元素
                    SetButtonStates(true, true, false);
                    UserHelp.Text = "press play\nor record";
                    StatusImag.Source = blankImage;
                }
            }
        }
        /// <summary>
        /// bufferready时间处理器。从麦克风获得音频数据,将其存储到一个buffer里面,其后可将这个buffer里德
        /// 东西写到数据流中以播放
        /// 这个时间处理器中的动作要保证很短,很快!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void microphone_BufferReady(object sender, EventArgs e)
        {
            //获取音频数据
            microphone.GetData(buffer);
            //将这些音频数据存到数据流中
            stream.Write(buffer, 0, buffer.Length);
        }
        /// <summary>
        /// 处理record_button点击事件
        /// 设置麦克风和数据缓冲以接收音频数据
        /// 然后启动麦克风,同时更新UI元素
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void reordButton_Click(object sender, EventArgs e)
        {
            //获取0.5秒的音频数据
            microphone.BufferDuration = TimeSpan.FromMilliseconds(500);
            //分配内存来接收这些数据
            buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];
            //先把数据流设置为0,防止原来就有数据
            stream.SetLength(0);
            //开始录音
            microphone.Start();


            SetButtonStates(false, false, true);
            UserHelp.Text = "record";
            StatusImag.Source = microphoneImage;
        }
        /// <summary>
        /// 处理play_button点击事件
        /// 播放从麦克风获取的音频数据,并更新UI元素
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void playButton_Click(object sender, EventArgs e)
        {
            if (stream.Length > 0)
            {
                SetButtonStates(false, false, true);
                UserHelp.Text = "play";
                StatusImag.Source = speakerImage;


                Thread soundThread = new Thread(new ThreadStart(playSound));
                soundThread.Start();
            }
        }
        /// <summary>
        /// 处理stop_button点击事件
        /// 停止录音,并更新UI元素
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void stopButton_Click(object sender, EventArgs e)
        {
            if (microphone.State == MicrophoneState.Started)
            {//正处在录音状态,则停止录音
                microphone.Stop();
            }
            else if (soundInstance.State == SoundState.Playing)
            {//正处在播放模式,则停止放音
                soundInstance.Stop();
            }

            SetButtonStates(true, true, false);
            UserHelp.Text = "ready";
            StatusImag.Source = blankImage;
        }
        /// <summary>
        /// 使用音效实例播放音频,以监控回放的状态
        /// </summary>
        private void playSound()
        {
            SoundEffect sound = new SoundEffect(stream.ToArray(), microphone.SampleRate, AudioChannels.Mono);
            soundInstance = sound.CreateInstance();
            soundIsPlaying = true;
            soundInstance.Play();
        }


        //设置三个按钮的属性
        private void SetButtonStates(bool recordEnabled, bool playEnabled, bool stopEnabled)
        {
            (ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = recordEnabled;
            (ApplicationBar.Buttons[1] as ApplicationBarIconButton).IsEnabled = playEnabled;
            (ApplicationBar.Buttons[2] as ApplicationBarIconButton).IsEnabled = stopEnabled;
        }
    }
}

程序中已经添加了注释,应该能看懂吧。只是哪些陌生的类和方法让人望而生畏。看来还是知道的太少,继续努力学习!!!

1、最上面的命名空间一定要好好看看有哪些,尤其是你自己亲自创建了工程的话(有些默认是不添加的,还得自己动手加进去)

2、XNAframework默认是没有加入到参考当中的,加入的方法是:在solution explorer中,右击references,点击add,选择xnaframework,就可以了!


这就完成了windows phone 7的录音,如果你是个有“艺术细菌”人,还可以用blend将界面的编的好看一点,如果你还懂isolate存储,就把它做得更强大一些吧。可怜我现在都不会,继续学习中。

很明显,上面这个只是对audio data 的简单的收集存储和播放,距离解析出想要的数据还有很长的路。关于解调和解码的东西,正在查!哪位大牛有这方面的资料,万望指教啊!!!(怎么从音频流中解析出我想要的数据。单片机和手机通过音频口相连,单片机端调制、编码,发到手机上,也就是说想要的数据是从单片机获得)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值