转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992

在APP市场上,常常有一些充满新意的应用让我们眼前一亮,比方微信的面对面加好友,支付宝的声波支付等等,都是通过声波的方式进行握手通信,今天这篇文章将介绍声波通信和声波验证的实现原理和代码实现。

首先介绍一下声波验证的原理。假设我们想发出声音,就必须震动,说话是声带在震动,手机能播放音乐是喇叭在震动。既然发出声音必须震动,那么就有震动快慢之分,我们把震动的快慢叫做声音的频率。频率低的声音低沉有力,能传播非常远的距离,比方说大象之间通信就是利用次声波,也就是频率非常低的声波进行的。而蝙蝠,我们都知道是通过超声波进行探路的,超声波就是震动频率比較高的声音。频率太高或者太低,人的耳朵都听不到,人耳的识别范围是20HZ-20000HZ。这里引出了一个单位,叫做赫兹(HZ),它是指一秒钟的震动次数。

知道什么是声音的频率之后,我们就能够開始介绍声波通信的原理了。既然不同的声音有不同的频率,那么我们就能够假设1000HZ的声音代表1,2000HZ的声音代表2,以此类推,我们就能够用不同的频率代表不同的数字组合。在接收到声波之后,再依据不同的频率解析成我们须要的数据就好。

假设我们想发出单频率的声音,我们就须要自己构造特定频率的正弦函数。手机喇叭在震动的时候,实际上是依据不同的电流带动鼓纸,进行不同频率的震动才发出声音的。而假设我们想要发出1000HZ的声音,我们就须要设计相应的正弦函数,来提供一定规律的电流。

既然说到我们要自己设计正弦函数,还有几个名词我要解释一下:

1.採样率

是指每一秒要採集的声音的次数。由于寻常我们说话的时候,产生的是模拟信号,就是时间连续的信号,假设我们想把语音录制下来怎么办呢?我们是做不到完全然全的都录制下来的,我们仅仅能每隔一段时间採集一次数据,将模拟信号转化成数字信号,因此,採样点的多少就影响到语音的质量了。假设採样点多,那么质量就高,听起来就和原声的区别小;相对的,採样点少,质量就次,听起来就和原声不一样。这就是採样率的作用。

2.採样定理

上面说道,假设採样率高,录音的质量就高,那么,是不是採样率越高越好呢?当然不是。随着採样率的提高,尽管质量提高了,可是採样的难度也相应的添加了,并且,採样出来的数据须要存储,採样率越高,产生的数据文件就越大,因此质量高的音乐比一般的音乐体积大。所以,我们通常要选用一个合适的採样率。在信号处理领域有一个定理叫做“採样定理”,也称“奈奎斯特定理”,内容是:假设採样的频率高于信号最高频率的两倍,採样之后的数字信号就能够完整的保留下原始信号中的信息。由于人的听力范围在20HZ-20000HZ,所以一般採样频率在44.1kHZ,也就是一分钟44100次。

在明确了这些预备知识之后,以下開始介绍开源项目SinVoice。

上面是整个项目的结构,圈中的基本的类,以下把几个重要的类的功能和注意点介绍一下。为了便于理解,我自己加入了一些凝视,并非有益侵占原作者的版权哈。

首先,我们先看一下究竟怎么用,以下是MainActivity的代码:

package com.example.sinvoicedemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView; import com.libra.sinvoice.LogHelper;
import com.libra.sinvoice.SinVoicePlayer;
import com.libra.sinvoice.SinVoiceRecognition; /**
*
* @ClassName: com.example.sinvoicedemo.MainActivity
* @Description: 声波通信
* @author zhaokaiqiang
* @date 2014-11-15 下午12:36:32
*
*/
public class MainActivity extends Activity implements
SinVoiceRecognition.Listener, SinVoicePlayer.Listener { private final static String TAG = "MainActivity";
// 最大数字
private final static int MAX_NUMBER = 5;
// 识别成功
private final static int MSG_SET_RECG_TEXT = 1;
// 開始识别
private final static int MSG_RECG_START = 2;
// 识别结束
private final static int MSG_RECG_END = 3; private final static String CODEBOOK = "12345"; private Handler mHanlder;
// 播放
private SinVoicePlayer mSinVoicePlayer;
// 录音
private SinVoiceRecognition mRecognition; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mSinVoicePlayer = new SinVoicePlayer(CODEBOOK);
mSinVoicePlayer.setListener(this); mRecognition = new SinVoiceRecognition(CODEBOOK);
mRecognition.setListener(this); final TextView playTextView = (TextView) findViewById(R.id.play_text);
mHanlder = new RegHandler((TextView) findViewById(R.id.regtext)); // 開始播放声音
findViewById(R.id.start_play).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String text = genText(15);
playTextView.setText(text);
mSinVoicePlayer.play(text);
}
}); // 停止播放声音
findViewById(R.id.stop_play).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mSinVoicePlayer.stop();
}
}); // 開始声音识别
findViewById(R.id.start_reg).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mRecognition.start();
}
}); // 停止声音识别
findViewById(R.id.stop_reg).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mRecognition.stop();
}
});
} // 获取长度为count且最大值为MAX_NUMBER的随机数
private String genText(int count) {
StringBuilder sb = new StringBuilder();
int pre = 0;
while (count > 0) {
int x = (int) (Math.random() * MAX_NUMBER + 1);
if (Math.abs(x - pre) > 0) {
sb.append(x);
--count;
pre = x;
}
} return sb.toString();
} private static class RegHandler extends Handler { private StringBuilder mTextBuilder = new StringBuilder();
private TextView mRecognisedTextView; public RegHandler(TextView textView) {
mRecognisedTextView = textView;
} @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_RECG_TEXT:
char ch = (char) msg.arg1;
mTextBuilder.append(ch);
if (null != mRecognisedTextView) {
mRecognisedTextView.setText(mTextBuilder.toString());
}
break; case MSG_RECG_START:
mTextBuilder.delete(0, mTextBuilder.length());
break; case MSG_RECG_END:
LogHelper.d(TAG, "recognition end");
break;
}
}
} @Override
public void onRecognitionStart() {
mHanlder.sendEmptyMessage(MSG_RECG_START);
} @Override
public void onRecognition(char ch) {
mHanlder.sendMessage(mHanlder.obtainMessage(MSG_SET_RECG_TEXT, ch, 0));
} @Override
public void onRecognitionEnd() {
mHanlder.sendEmptyMessage(MSG_RECG_END);
} @Override
public void onPlayStart() {
LogHelper.d(TAG, "start play");
} @Override
public void onPlayEnd() {
LogHelper.d(TAG, "stop play");
} }

我们能够看出,声波播放和识别的代码封装的非常easy易用,我主要强调以下几点

1.常量CODEBOOK是一个编码本,由于是这个功能能够商用,因此开源的代码中仅仅给出了使用12345这5个数字进行编码的实例,所以这个常量不要改动。

2.SinVoicePlayer和SinVoiceRecognition是两个非常重要的类,前者能够实现将数字转化成单频率的音频进行输出,后者则能够依据音频进行识别。我们能够设置监听器,来监听识别成功的事件回调。

3.genText(int count) 方法是为了获取一个长度是count的随机数,并且这个随机数是有要求的,由于演示样例代码仅仅实现了1到5的编码和解码,因此,生成的随机数必须在1到5之间才干进行正确的编解码,所以使用MAX_NUMBER进行随机数的大小控制

假设仅仅是想简单的使用这个功能,了解上面的知识之后,就全然能够用了,下一篇文章中,我将介绍实现过程中的一些细节问题,下一篇再见。

项目的Github地址:https://github.com/JesseGu/SinVoice

【Android开发经验】移动设备的“声波通信/验证”的实现——SinVoice开源项目介绍(一)的更多相关文章

  1. android studio 使用jar包,arr包和怎么使用githup开源项目中的aar包或module

    我这里的android studio的版本是2.2.3版本 一.现在大家都用android studio了,就有人问怎么使用jar包 其实使用jar包比较简单 直接吧jar放入工程的app目录下的li ...

  2. android开发中在界面上实现曲线图的几个开源项目

    转自:https://wapiknow.baidu.com/question/1959128379041474620?qq-pf-to=pcqq.c2c 几个相关开源项目: 1.  MPAndroid ...

  3. [android] androidPN开源项目介绍

    打开androidPN项目,会看到server和client两份代码 server部分 找到server的代码,开启服务,双击 bin/run.bat ,服务启动后监听127.0.0.1:7070端口 ...

  4. Android中通过ViewHelper.setTranslationY实现View移动控制(NineOldAndroids开源项目)

    我们知道有不少开源project,能实现非常多不错的效果.前几天,我看了一个效果,刚好项目中也用到了这个jar包. 没事挖一挖 学一学(一说到挖一挖.那么问题来了.挖掘机技术究竟哪家强 ),看看不错的 ...

  5. Android开源项目分类汇总

    目前包括: Android开源项目第一篇——个性化控件(View)篇   包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView. ...

  6. GitHub上史上最全的Android开源项目分类汇总 (转)

    GitHub上史上最全的Android开源项目分类汇总 标签: github android 开源 | 发表时间:2014-11-23 23:00 | 作者:u013149325 分享到: 出处:ht ...

  7. Android开源项目汇总【转】

    主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.ProgressBar.TextView ...

  8. GitHub上史上最全的Android开源项目分类汇总

    今天在看博客的时候,无意中发现了 @Trinea 在GitHub上的一个项目 Android开源项目分类汇总 ,由于类容太多了,我没有一个个完整地看完,但是里面介绍的开源项目都非常有参考价值,包括很炫 ...

  9. Android 开源项目分类汇总(转)

    Android 开源项目分类汇总(转) ## 第一部分 个性化控件(View)主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Galler ...

随机推荐

  1. 程序猿的量化交易之路(26)--Cointrader之Listing挂牌实体(13)

    转载须注明出处:http://blog.csdn.net/minimicall? viewmode=contents,http://cloudtrade.top Listing:挂牌. 比方某仅仅股票 ...

  2. 设定十分钟android在状态栏上集成的开源project推荐

    1.前言 于android kitkat 有一个新功能可以设置背景的手机状态栏,让手机风的整个界面格是一致的,它看起来非常酷,在今年的google i/o向上android l这样的风格.来如今看我们 ...

  3. Swift - 使用UIView给页面添加4×4方格

    1,下面是一个利用UIView来给页面上绘制灰色方块的例子,效果图如下:    代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...

  4. HDU 3853 期望概率DP

    期望概率DP简单题 从[1,1]点走到[r,c]点,每走一步的代价为2 给出每一个点走相邻位置的概率,共3中方向,不动: [x,y]->[x][y]=p[x][y][0] ,  右移:[x][y ...

  5. Android installed app, never used, cannot receiver BroadcastReceiver

    官方文档是这么写的:(http://developer.android.com/about/versions/android-3.1.html#launchcontrols) Launch contr ...

  6. Android相关

    wifi密码:因为我们安卓系统的手机无线账号数据是储存在一个文件里的,那就是 /data/misc/wifi/wpa_supplicant.conf ,这个是系统文件,权限不够高是无法访问的,而这个文 ...

  7. Android开源项目大全 - 工具类

    主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. 一.依赖注入DI 通过依赖注入减少Vie ...

  8. POJ2599+POJ2082【最大矩形面积】

    题目链接:http://poj.org/problem?id=2559 题目链接:http://poj.org/problem?id=2082 这一类题目的解法,不知自己闲着没事就做了两个. 果然压栈 ...

  9. C语言中字符串如何转换为二进制、八进制、十进制、十六进制

    在C语言某个程序当中需要把文本16进制转换成对应的16进制数,比如字符串"0x1a"转换成10进制的26,可以用以下函数来实现 相关函数: atof, atoi, atol, st ...

  10. Terracotta收购Ehcache (转)

    随着Terracotta对Ehcache的收购成行,业界两大知名的开源Java缓存产品走到了一起.以提供JVM级“POJO集群”而闻名于世的Terracotta可以将运行在单个JVM上的多线程应用移植 ...