android音频通信
来源:互联网 发布:excel2003删除重复数据 编辑:程序博客网 时间:2024/06/05 10:29
这是前一段时间遇到的问题了, 想用android手机的音频口发送消息,消息内容可以是字符串,可以是命令,甚至可以是文件。由于智能手机的普及,今后在工业领域可能会推广,所以在这里分享一下。
现在开始:
一(语文是硬伤,标题想不出来):
本例只实现了发送字符串的功能(用的是方波标记),而且界面布局很简单,贴图:
点击【send】将会发送出一段噪音,噪音的内容是用你所输入的字符串编码过来的,用的是Ascall码转换成高低电频,当然在手机的耳机插口需要插入一个自己开发的信号转换器,接收端需要安装配套的信号接受器,而且成本很低,似乎是用单片机开发的。好吧,露馅了,我不懂硬件……
绑定button。
listener = new Listener();play = (Button)findViewById(R.id.play);text = (EditText)findViewById(R.id.text);play.setOnClickListener(listener);
listener的内容:
private class Listener implements OnClickListener{@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubsendme = text.getText().toString();Log.d("!!!!!!","listener");if(sendme != ""&& sendme != null){if(thread == null){thread = new AudioThread();thread.start();}elsethread.letRun();}}}
thread的内容:
class AudioThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubwhile(true){if(isrun){Log.d("!!!!!!","runner");audioplayer = new AudioSend();audioplayer.play(sendme);try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}isrun =false;}}}public void letRun(){Log.d("!!!!!!","letrunner");isrun = true;}}
已经发现重点就在audioplayer这个对象,这个是自己编写的audiosend类构造的,运用的是AudioTrack,查看api就可以发现这个类有个write()方法,方法是重载的:write(byte【】,int,int)或者是write(short【】,int,int),那么数组中包含的究竟是什么?
二:数组内容解析
先来了解下耳机的构造:(耳机够着此段转载于http://blog.csdn.net/xl19862005/article/details/8522869)
我们知道,耳机是用来听音乐,打电话的,既然是和声音相关的,那么耳机线上传输的就是音频信号,常见的音频信号一般都是在100Hz——10KHz左右的范围内,那么手机里面的音频输出系统(DA和音频功放)的幅频特性(也既带宽)一定也是在这个范围(这是本人的猜想,由于设备和仪器有限,没有进行系统的测试,有兴趣的朋友可以用相关的测试仪器测测),那么,既然有带宽,好家伙,我们就可以通过努力在这个频带内实现我们的通信信道了!另外值得提的一点是,耳机线上传输的音频信号是交流的!
下面我们来看看市面上常见的耳机座(公头)的引脚定义,android手机上用的耳机大多都是3.5mm的四芯座,在这四个芯中,分别是:地、左声道、右声道和线控开关(MIC)
1、国家标准
三:audiosend类内容:
public class AudioSend {static int baudRate = 4800;static int maxRate = 48000;static int delayBit = 0;private static byte ihigh = (byte) (-128);private static byte ilow = (byte) (16);AudioTrack audioplayer;static int minSize;static byte[] getBuffer(String str){int bytesinframe = delayBit + 10;//delay + 8bit + 一个标识开始的位 + 一个标识结束的位byte[] sendme = str.getBytes();int n = maxRate/baudRate;boolean[] bits = new boolean[sendme.length * bytesinframe];//byte[] waveform = new byte[(sendme.length*bytesinframe* n)]; //防止失真,延长每个波的变化的播放时间Arrays.fill(bits, true); //当其不断传出电流的时候标志着无信息传送,一旦有低压电流标志开始传送数据int i,m,k,j = 0;for (i=0;i<sendme.length;++i){m=i*bytesinframe;bits[m]=false;bits[++m]=((sendme[i]&1)==1);//位操作,也可以先转换成数字再用 Integer.toBinaryStringbits[++m]=((sendme[i]&2)==2);bits[++m]=((sendme[i]&4)==4);bits[++m]=((sendme[i]&8)==8);bits[++m]=((sendme[i]&16)==16);bits[++m]=((sendme[i]&32)==32);bits[++m]=((sendme[i]&64)==64);bits[++m]=((sendme[i]&128)==128);//加上延时的位for(k=0;k<bytesinframe-9;k++) bits[++m]=true;}//转换成需要的byte数组for (i=0;i<bits.length;i++){for (k=0;k<n;k++){waveform[j++]=(bits[i])?((byte) (ihigh)):((byte) (ilow));}}bits=null;return waveform;}public void play (String str){byte[] send = getBuffer(str);minSize = AudioTrack.getMinBufferSize(48000,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);audioplayer = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT, minSize, AudioTrack.MODE_STREAM);audioplayer.play();audioplayer.write(send, 0, send.length);audioplayer.stop();audioplayer.release();}}
在够着audiotrack的时候
minSize = AudioTrack.getMinBufferSize(48000,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);audioplayer = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT, minSize, AudioTrack.MODE_STREAM);
第一行其实是获取最小缓冲区大小,阐述按顺序依次是采样率,声道,和采样精度,在这里简单讲一下,如果还不懂还是自己google吧如果画成坐标图,横轴是时间,纵轴是电流的话:
采样率就是每秒钟要发送多少个点过去,也就是告诉audiotrack对象每秒需要从我所write的数组中提取多少个点,当然在播放音乐的时候采样率越高就会音质效果越好。我们来极端假设一下,如果采样率是1,(其实android上只能是4800,44100,48000)那么意味着你一秒这个区段听到的声音都是一样的,不敢想象,它会吧”忐忑“播成什么样。
声道不废话了
采样精度就是电流的强度的上限和下限,当然也是越大音质越好,目前似乎只能是8BIT和16BIT,应该也就是这个原因所以write接受的是byte和short数组吧。
接下来将编码:
对于编码也就是我的代码的getbuffer方法了。
先来讲一下通信的协议吧。如图所示通信协议中每十个位标记位发送的一个字母,开始位定义成低电流终止位定义成高电流(我们没有定奇偶校检位),中间的八位来定义字母的内容(也就是字母转换成Acall码之后的内容)但是每个电流如果用1和0表示的话差别太小了,单片机很可能检测不到,或者检测失误,所以我将高电流定义为-128,低电流定义为16,代码先将每个字母转化成对应的ascll码,然后再将它转换成对应的高低电流的波峰和波谷。
对于
//转换成需要的byte数组for (i=0;i<bits.length;i++){for (k=0;k<n;k++){waveform[j++]=(bits[i])?((byte) (ihigh)):((byte) (ilow));}}
- android音频通信
- android 音频口通信
- Android、ios 音频编解码 音频口通信 音频通信
- android arduino音频通信模块 支持双向通信
- android音频口通信——2FSK信号调制
- android音频口通信——2FSK信号调制
- android下调试声卡驱动之I2S音频通信
- 手机音频口通信
- andriod音频通信技术
- 音频通信源码分析
- 音频通信去啸叫
- android 音频
- android音频
- Android 音频
- Android 音频
- 基于手机音频通信应用
- 基于手机音频通信应用
- 如何修改音频通信质量?
- Android DOM解析XML
- InputStream 和 OutputStream
- Visual Studio 的Build Event 使用
- VS2012 下载地址
- Hibernate映射解析——七种映射关系(转来备忘)
- android音频通信
- FileInputStream 和 FileOutputStream
- 处理 url类
- asic码对照表
- 读写锁(Read-Write Lock)的一种实现
- ucgui的menu的改进
- 丢包了
- (Android 开源项目 android pn) 整合androidpn与SSH
- Ubuntu Server下Nagios可视化绘制工具PNP安装与配置