|
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 实现一个简单的语音聊天室(源码) - 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) 二维码:
本文链接:闲谈神经网络--写给初学者(三),转载请注明。 阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 在 CentOS 6.x 上安装最新版本的 git - make_dream 阅读原文»在 CentOS 的默认仓库中有git,所以最简单的方法是: $ sudo yum install git 这种方法虽然简单,但是一般仓库里的版本更新不及时,比如 CentOS 仓库中的 git 最新版是1.7.1(今天是2014-10-28),但是 git 官方已经到2.x 的版本了。 这时,就不得不动用最终的大杀器了,通过自己编译源码安装。
步骤如下: 1. 需要给 CentOS 下载安装编译工具。 $ sudo yum groupinstall “Development Tools” 2. 安装一些 git 构建或执行时需要的其他依赖。 $ sudo yum install zlib-devel perl-ExtUtils-MakeMaker asciidoc xmlto openssl-devel 3. 下载 git 最新版本的源代码 $ cd ~ $ wget -O git.zip https://github.com/git/git/archive/master.zip 4. 解压源文件 $ unzip git.zip $ cd git-master 5. 构建并安装
$ autoconf $ ./configure $ make && make install 6. 创建link
$ ln -s /usr/local/bin/git /usr/bin/ 如果系统中已经安装过旧的版本,步骤6可能会报文件已存在的错误,这个时候需要把旧的 link 删掉再重新 link。
7. 检查 git 版本 $ git --version 此时,应该显示为 git 的最新版本。
本文链接:在 CentOS 6.x 上安装最新版本的 git,转载请注明。 Android输出日志Log类 - 宇少095 阅读原文»android.util.Log常用的方法有以下5个: Log.v() Log.d() Log.i() Log.w() 以及 Log.e()。根据首字母分别对应VERBOSE,DEBUG,INFO,WARN,ERROR。
1、Log.v 的调试颜色为黑色的,任何消息都会输出,这里的v代表verbose�嗦的意思,平时使用就是Log.v("","");
2、Log.d的输出颜色是蓝色的,仅输出debug调试的意思,但他会输出上层的信息,过滤起来可以通过DDMS的Logcat标签来选择。
3、Log.i的输出为绿色,一般提示性的消息information,它不会输出Log.v和Log.d的信息,但会显示i、w和e的信息。
4、Log.w的意思为橙色,可以看作为warning警告,一般需要我们注意优化Android代码,同时选择它后还会输出Log.e的信息。
5、Log.e为红色,可以想到error错误,这里仅显示红色的错误信息,这些错误就需要我们认真的分析,查看栈的信息了。
1 public class MyLog { 2 private static Boolean MYLOG_SWITCH = true; // 日志文件总开关 3 private static Boolean MYLOG_WRITE_TO_FILE = true; // 日志写入文件开关 4 private static char MYLOG_TYPE = 'v'; // 输入日志类型,w代表只输出告警信息等,v代表输出所有信息 5 private static String MYLOG_PATH_SDCARD_DIR = "/sdcard/"; // 日志文件在sdcard中的路径 6 private static int SDCARD_LOG_FILE_SAVE_DAYS = 0; // sd卡中日志文件的最多保存天数 7 private static String MYLOGFILEName = "Log.txt"; // 本类输出的日志文件名称 8 private static SimpleDateFormat myLogSdf = new SimpleDateFormat( 9 "yyyy-MM-dd HH:mm:ss"); // 日志的输出格式 10 private static SimpleDateFormat logfile = new SimpleDateFormat("yyyy-MM-dd"); // 日志文件格式 11 public Context context; 12 13 public static void w(String tag, Object msg) { // 警告信息 14 log(tag, msg.toString(), 'w' ); 15 } 16 17 public static void e(String tag, Object msg) { // 错误信息 18 log(tag, msg.toString(), 'e' ); 19 } 20 21 public static void d(String tag, Object msg) { // 调试信息 22 log(tag, msg.toString(), 'd' ); 23 } 24 25 public static void i(String tag, Object msg) { // 26 log(tag, msg.toString(), 'i' ); 27 } 28 29 public static void v(String tag, Object msg) { 30 log(tag, msg.toString(), 'v' ); 31 } 32 33 public static void w(String tag, String text) { 34 log(tag, text, 'w' ); 35 } 36 37 public static void e(String tag, String text) { 38 log(tag, text, 'e' ); 39 } 40 41 public static void d(String tag, String text) { 42 log(tag, text, 'd' ); 43 } 44 45 public static void i(String tag, String text) { 46 log(tag, text, 'i' ); 47 } 48 49 public static void v(String tag, String text) { 50 log(tag, text, 'v' ); 51 } 52 53 /** 54 * 根据tag, msg和等级,输出日志 55 * 56 * @param tag 57 * @param msg 58 * @param level 59 * @return void 60 * @since v 1.0 <阅读更多内容
本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订 。 用Linux Shell脚本轻松管理Radius服务器 阅读原文» 公司的无线环境采用mac地址认证的方式,mac地址被绑定到Radius的users配置文件中,将注册了的mac地址作为用户名和密码。为了方便的管理这些mac地址,自己写了一个shell脚本来管理。 shell脚本所特有的强大文本处理能力和各种命令函数的组合,使得管理员的工作能轻松不少。 下面就列出该脚本的功能以示参考: -
添加mac地址 -
删除mac地址 -
查找mac地址 -
去除重复mac地址 -
检查mac地址合法性 -
TODO,导入导出mac地址,添加注释
其中用到的Shell脚本技术包括但不限于: -
文本文件的列处理和行处理,如sed、awk等命令 -
字符串查找、过滤、大小写转换,bash和grep等命令 -
获取、计算、比较字符串长度,bash和wc等命令 -
mac地址正则表达式的处理和类型转换 -
shell编程操作、包括文件包含、函数、参数传递、返回值等 -
其他
代码示例: #!/bin/bash # # Source function library. . /etc/rc.d/init.d/functions RADIUSD=/usr/sbin/radiusd LOCKF=/var/lock/subsys/radiusd CONFIG=/etc/raddb/radiusd.conf USERCONFIG=/etc/raddb/users [ -f $RADIUSD ] || exit 0 [ -f $CONFIG ] || exit 0 [ -f $USERCONFIG ] || exit 0 RETVAL=0 OPERATION=$1 MACADDRESS=$2 function help() { clear echo $"" echo $"====================================================================================" echo $"For Radius on Fedora/CentOS/RadHat Linux Server, Written by Chris" echo $"====================================================================================" echo $"A tool to manage Radius server" echo $"" echo $"Usage: $0 {find|add|modify|delete|check|remove|start|stop|status|restart|reload} mac" #TODO echo $"Usage: $0 {import|export|debug}" echo $"" echo $"For more information please contract dgdenterprise@gmail.com" echo $"====================================================================================" echo $"" exit 1 } function mac() { if [ -z $MACADDRESS ];then echo $"no mac address is signed! " echo $"\$2 is $MACADDRESS" exit 1 else if [[ "${#MACADDRESS}" != "12" ]] && [[ "${#MACADDRESS}" != "17" ]] ;then echo "mac length is ${#MACADDRESS}" echo "mac address is illegal! " exit 1 # else # echo $"mac which you input is $MACADDRESS" fi #echo $MACADDRESS | sed -nr '/[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}/p' #echo $MACADDRESS | sed -nr '/[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}/p' #echo $MACADDRESS | sed -nr '/[A-Fa-f0-9]{12}/p' if [[ `echo $MACADDRESS | grep -` ]];then PROMAC=`echo $MACADDRESS | sed -nr '/[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}-[A-Fa-f0-9]{2}/p' | tr '[:upper:]' '[:lower:]' | sed 's/-//g'` elif [[ `echo $MACADDRESS | grep :` ]];then PROMAC=`echo $MACADDRESS | sed -nr '/[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2}/p' | tr '[:upper:]' '[:lower:]' | sed 's/://g'` else PROMAC=`echo $MACADDRESS | tr '[:upper:]' '[:lower:]'` fi echo $PROMAC fi } function find() { MAC=`mac` echo $"accepted mac is $MAC" if [[ `grep $MAC $USERCONFIG` ]]; then MACLINE=`grep -n $MAC $USERCONFIG | awk -F ':' '{print $1}'` #echo $MACLINE MACLINECOUNT=$(echo $MACLINE | wc -w) #echo $MACLINECOUNT if [[ "$MACLINECOUNT" != "1" ]];then echo $"ERROR, this mac $MAC has duplicate record, you should use $0 remove $MAC to remove duplicate record" exit 1 fi echo $"Successfully find $MAC in $MACLINE line of file $USERCONFIG! " echo REVAL=$? else echo $"Can not find $MAC in file $USERCONFIG! " echo exit 1 REVAL=$? fi } function add() { MAC=`mac` echo $"accepted mac is $MAC" #find $MAC LINENUM=`grep -n "Cleartext-Password :='" users | grep -v \# | head -n1 | awk -F ":" '{print $1}'` SEDOPERATION=$LINENUM"a" sed -i "$SEDOPERATION $MAC Cleartext-Password :='$MAC'" $USERCONFIG find $MAC restart } function modify() { MAC=`mac` find $MAC #TODO } function delete() { MAC=`mac` echo $"accepted mac is $MAC" if [[ `grep $MAC $USERCONFIG` ]]; then MACLINE=`grep -n $MAC $USERCONFIG | awk -F ':' '{print $1}'` ##echo $MACLINE #MACLINECOUNT=$(echo $MACLINE | wc -w) ##echo $MACLINECOUNT #if [[ "$MACLINECOUNT" != "1" ]];then # echo $"ERROR, this mac $MAC has duplicate record, you should use $0 remove $MAC to remove duplicate record" # exit 1 #fi echo $"Successfully find $MAC in $MACLINE line of file $USERCONFIG! " echo $"It will be deleted! " sed -i "$MACLINE d" $USERCONFIG #TODO echo $"If you see 'Can not find $MAC in file $USERCONFIG! ', it means successfully! " find $MAC echo REVAL=$? else echo $"Can not find $MAC in file $USERCONFIG! " echo REVAL=$? fi } function check() { MAC=`mac` find $MAC remove $MAC } function remove() { MAC=`mac` echo $"accepted mac is $MAC" #TODO #echo $"backuped file to file $FILENAME" if [[ `grep $MAC $USERCONFIG` ]]; then MACLINE=`grep -n $MAC $USERCONFIG awk -F ':' '{print $1}'` #echo $MACLINE MACLINECOUNT=$(echo $MACLINE wc -w) #echo $MACLINECOUNT if [[ "$MACLINECOUNT" == "1" ]];then echo $"WARNNING, this mac $MAC is good record, no duplicate record has found! " exit 0 fi TOREMOVE="$MAC Cleartext-Password :='$MAC'" sed -i "/^$TOREMOVE$/d" $USERCONFIG add $MAC fi } function restart() { service radiusd restart } function reload() { service radiusd reload } function status() { service radiusd status } case "$1" in find) find RETVAL=$? ;; add) add RETVAL=$? ;; modify) modify RETVAL=$? ;; delete) delete RETVAL=$? ;; check) check RETVAL=$? ;; remove) remove RETVAL=$? ;; start) start RETVAL=$? ;; stop) stop RETVAL=$? ;; status) status RETVAL=$? ;; restart) restart RETVAL=$? ;; reload) reload RETVAL=$? ;; *) help exit 1 ;; esac 其中有一些可以改进的地方,比如换一种方法或者增强用户的使用体验都是可以的,欢迎大家提出意见。 本文出自 "通信,我的最爱" 博客,请务必保留此出处http://dgd2010.blog.51cto.com/1539422/1567085 |