2014年10月29日星期三

实现一个简单的语音聊天室(源码) - zhuweisky

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
实现一个简单的语音聊天室(源码) - zhuweisky  阅读原文»

  语音聊天室,或多人语音聊天,是即时通信应用中常见的功能之一,比如,QQ的语音讨论组就是我们用得比较多的。

这篇文章将实现一个简单的语音聊天室,让多个人可以进入同一个房间进行语音沟通。先看运行效果截图:

  

   从左到右的三张图分别是:登录界面、语音聊天室的主界面、标注了各个控件的主界面。

  (如果觉得界面太丑,没关系,后面下载源码后,你可以自己美化~~)

一. C/S结构

  很明显,我这个语音聊天室采用的是C/S结构,整个项目结构相对比较简单,如下所示:

   该项目的底层是基于OMCS构建的。这样,服务端就基本没写代码,直接把OMCS服务端拿过来用;客户端就比较麻烦些,下面我就重点讲客户端的开发。

二. 客户端控件式开发

  客户端开发了多个自定义控件,然后将它们组装到一起,以完成语音聊天室的功能。为了便于讲解,我主界面的图做了标注,以指示出各个自定义控件。  

  现在我们分别介绍各个控件:

1. 分贝显示器

  分贝显示器用于显示声音的大小,比如麦克风采集到的声音的大小,或扬声器播放的声音的大小。如上图中3标注的。

(1)傅立叶变换

  将声音数据转换成分贝强度使用的是傅立叶变换。其对应的是客户端项目中的FourierTransformer静态类。源码比较简单,就不贴出来了,大家自己去看。

(2)声音强度显示控件 DecibelDisplayer

  DecibelDisplayer 使用的是PrograssBar来显示声音强度的大小。

  每当有声音数据交给DecibelDisplayer显示时,首先,DecibelDisplayer会调用上面的傅立叶变换将其转换为分贝,然后,将其映射为PrograssBar的对应的Value。

2.发言者控件 SpeakerPanel

  SpeakerPanel 用于表示聊天室中的一个成员,如上图中1所示。它显示了成员的ID,成员的声音的强度(使用DecibelDisplayer控件),以及其麦克风的状态(启用、引用)。

  这个控件很重要,我将其源码贴出来:

public partial class SpeakerPanel : UserControl ,IDisposable
{
private ChatUnit chatUnit;

public SpeakerPanel()
{
InitializeComponent();
this.SetStyle(ControlStyles.ResizeRedraw, true);//调整大小时重绘
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);// 双缓冲
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);// 禁止擦除背景.
this.SetStyle(ControlStyles.UserPaint, true);//自行绘制
this.UpdateStyles();
}

public string MemberID
{
get
{
if (this.chatUnit == null)
{
return null;
}

return this.chatUnit.MemberID;
}
}

public void Initialize(ChatUnit unit)
{
this.chatUnit = unit;
this.skinLabel_name.Text = unit.MemberID;

this.chatUnit.MicrophoneConnector.ConnectEnded += new CbGeneric<OMCS.Passive.ConnectResult>(MicrophoneConnector_ConnectEnded);
this.chatUnit.MicrophoneConnector.OwnerOutputChanged += new CbGeneric(MicrophoneConnector_OwnerOutputChanged);
this.chatUnit.MicrophoneConnector.AudioDataReceived += new CbGeneric<byte[]>(MicrophoneConnector_AudioDataReceived);
this.chatUnit.MicrophoneConnector.BeginConnect(unit.MemberID);
}

public void Initialize(string curUserID)
{
this.skinLabel_name.Text = curUserID;
this.skinLabel_name.ForeColor = Color.Red;
this.pictureBox_Mic.Visible = false;
this.decibelDisplayer1.Visible = false;
}

void MicrophoneConnector_AudioDataReceived(byte[] data)
{
this.decibelDisplayer1.DisplayAudioData(data);
}

void MicrophoneConnector_OwnerOutputChanged()
{
if (this闲谈神经网络--写给初学者(三) - 吴广磊  阅读原文»

  接上篇。

  前面两篇讲解了神经网络就是一个黑箱,里面有一个一个的小圆球(神经元)连接而成,通过改变神经元的连接方式及各个参数,就可以实现一个符合要求的神经网络。接下来我们来举一个BP神经网络的例子,以加深理解。

  在讲解这个例子之前,大概说一下一个神经网络解决问题的思路:

  1.对要解决的问题进行理解,找到输入输出数据。

  2.把已知的输入输出数据分为两部分:一部分用来训练网络;另外一部分来验证训练的网络到底好不好用。

  3.对输入数据进行预处理及归一化处理。

  4.创建合适的网络,如BP、感知器、RBF、Hopfield等等。(其实是先建立一个神经网络的黑箱子)

  5.设置网络训练参数,例如设置训练函数,学习函数、激活函数等等。

  6.使用输入输出训练网络。(其实是把黑箱子里面的神经元的各个参数给训练和学习合适了)

  7.使用验证数据验证网络。

  8.验证后觉得网络还不错,就可以实际应用,在实际应用过程中,还可以再对模型进行优化、重构等等。

下面开始我们例子的说明,用一个传统的花分类的例子(http://en.wikipedia.org/wiki/Iris_flower_data_set ):大概意思是:给你一朵花的四个特征,神经网络输出它的品种(共有三个品种)。

所以每一个样本的输入:四个数据,代表花的四个特征;输出:一个数据,代表花的品种,分别为1,2,3代表三个不同的品种。

样本数据为:http://files.cnblogs.com/wuguanglei/%E6%95%B0%E6%8D%AE.rar

其中trainData.txt用作训练数据,testData.txt用作验证数据。Matlab程序代码如下:

%0.操作前
clear;
close all;
clc;
%1.读入训练数据
[f1,f2,f3,f4,class] = textread('trainData.txt' , '%f%f%f%f%f',150);
input=[f1,f2,f3,f4]';%神经网络是一列算做一个样本输入,因此矩阵要转置一下
output=class';
%2.输入数据归一化
= mapminmax(input) ;
minI=Se.xmin;
maxI=Se.xmax;
%3.构造输出数据矩阵
s = length( class) ;%输出为1,2,3,这用1 0 0表示1;0 1 0表示2;0 0 1表示3
output = zeros( 3, s ) ;
for i = 1 : s
output( class( i ),i ) = 1 ;
end

%4.创建神经网络
net = newff( minmax(input) , [70 3] , { 'logsig' 'logsig' } , 'traingdx' ) ; %其中70表示第一层70个神经元,第二层30个神经元,后面几个参数分别设置的是激活函数和训练函数。

%5.设置训练参数
net.trainparam.show = 40 ;
net.trainparam.epochs = 600 ;
net.trainparam.goal = 0.01 ;
net.trainParam.lr = 0.01 ;

%6.开始训练
[net,tr,e] = train( net, input , output ) ;

%7.测试网络
[t1 t2 t3 t4 c] = textread('testData.txt' , '%f%f%f%f%f',150);
testInput=[t1,t2,t3,t4]';
testInput = mapminmax (testInput ) ;
Y = sim( net , testInput ) ;

%8.统计结果
[s1 , s2] = size( Y ) ;
hitNum = 0 ;
for i = 1 : s2
[m , Index] = max( Y( : , i ) )
if( Index == c(i) )
hitNum = hitNum + 1 ;
end
end
sprintf('识别率是 %0.3f%%',100 * hitNum / s2 )

详细讲解看代码注释吧。

就先写到这儿吧,对于入门,应该够了。

============================

最近帮朋友弄了微信公众号,每天早上6点30分,发送一个60秒的语音,有兴趣的朋友不妨关注一下。

微信号:歪理邪说(wailixs)

二维码:


本文链接:闲谈神经网络--写给初学者(三),转载请注明。

阅读更多内容

没有评论:

发表评论