申请这个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文件内容:
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">
Source="Images/blank.png" Margin="61,0,53,97" />
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
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));
}
///
/// 更新xna定时器分配,检查是否有音乐正在播放
/// 如果声音已经停止播放,将更新UI
///
///
///
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;
}
}
}
///
/// bufferready时间处理器。从麦克风获得音频数据,将其存储到一个buffer里面,其后可将这个buffer里德
/// 东西写到数据流中以播放
/// 这个时间处理器中的动作要保证很短,很快!
///
///
///
void microphone_BufferReady(object sender, EventArgs e)
{
//获取音频数据
microphone.GetData(buffer);
//将这些音频数据存到数据流中
stream.Write(buffer, 0, buffer.Length);
}
///
/// 处理record_button点击事件
/// 设置麦克风和数据缓冲以接收音频数据
/// 然后启动麦克风,同时更新UI元素
///
///
///
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;
}
///
/// 处理play_button点击事件
/// 播放从麦克风获取的音频数据,并更新UI元素
///
///
///
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();
}
}
///
/// 处理stop_button点击事件
/// 停止录音,并更新UI元素
///
///
///
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;
}
///
/// 使用音效实例播放音频,以监控回放的状态
///
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 的简单的收集存储和播放,距离解析出想要的数据还有很长的路。关于解调和解码的东西,正在查!哪位大牛有这方面的资料,万望指教啊!!!(怎么从音频流中解析出我想要的数据。单片机和手机通过音频口相连,单片机端调制、编码,发到手机上,也就是说想要的数据是从单片机获得)