iOS开发之音频口通信-通过方波来收发数据
之前做过的项目有需要通过音频口通信用方波来收发数据,由于这方面的资料比较少,下面就介绍下其原理,希望能给大家帮助。
一. 音频通信简介
大家应该都知道支付宝声波支付和拉卡拉吧,它们都是利用手机的音频口(手机耳机口)来实现全双工的通信(手机与设备之间的双向通信)。其优点是低成本,编码芯片成本低,手机的 3.5mm 通信接口广泛。
二. 市场应用
支付宝声波支付
手机刷卡器
皮肤检测仪
检测如甲醛、气压、温度、湿度等等
心率、血压等等
.......................
三. 通信原理
手机上用的耳机大多都是3.5mm的四芯座,在这四个芯中,分别是:地(GND)、左声道(L)、右声道(R)和线控开关(MIC)。
左右声道作用:向外设扩展头供电和发送数据
MIC作用:接收数据
市场上耳机主要有两种标准:国内标准(如下图所示),国际标准(MIC和GND和国内标准是反的,其他一样)
声音波形调制有调幅(AM)、调频(FM)和调相(PM)三种,而调制又有模拟调制和数字调制之分。(模拟调制和数字调制基本知识参考来源)
模拟调制:这种编码方式是将数字数据调制成模拟信号进行传输。通常采用三种模拟信号的载波特性(振幅、频率和相位)之一来表示被调制的数字数据,并由此产生三种基本调制方式。
(1) 幅移键控(ASK)法
ASK(Amplitude Shift Keying)是使用载波频率的两个不同振幅来表示两个二进制值。在一般情况下,用振幅恒定载波的存在与否来表示两个二进制字。ASK方式的编码效率较低,容易受增益变化的影响,抗干扰性较差。在音频电话线路上,一般只能达到 1200 b/s的传输速率。
(2) 频移键控(FSK)法
FSK(Frequency Shift Keying)是使用载波频率附近的两个不同频率来表示两个二进制值。FSK比ASK的编码效率高,不易受干扰的影响,抗干扰性较强。在音频电话线路上的传输速率可以大于1 200 b/s。
(3) 相移键控(PSK)法
PSK(Phase Shift Keying)是使用载波信号的相位移动来表示二进制数据。在PSK方式中,信号相位与前面信号序列同相位的信号表示 0,信号相位与前面信号序列反相位的信号表示 1。PSK方式也可以用于多相的调制,例如在四相调制中可把每个信号序列编码为两位。PSK方式具有很强的抗干扰能力,其编码效率比FSK还要高。在音频线路上,传输速率可达 9600b/s。
这些信号调制技术主要用于调制解调器(Modem)中。在实际的Modem中,一般将这些基本的调制技术组合起来使用,以增强抗干扰能力和编码效率。常见的组合是PSK和FSK方式的组合或者PSK和ASK方式的组合。
数字信号编码: 对于传输数字信号来说,最简单的信号编码方法是用信号的两个不同电压值来表示两个二进制数据。例如,用无电压来表示 0,用恒定的正电压表示 1;也可用正电压表示 1,而用负电压表示 0。然而,为了提高信号抗干扰能力,并且便于信号接收同步,通常采用更为有效的信号编码方法。
常用的数字信号编码有不归零 NRZ (Non Return to Zero)码、差分不归零DNRZ 码、曼彻斯特(Manchester)码及差分曼彻斯特(Differential Manchester)码等。
(1) NRZ码
NRZ码是用信号的幅度来表示二进制数据的,通常用正电压表示数据“1”,用负电压表示数据“0”,并且在表示一个码元时,电压均无需回到零,故称不归零码。NRZ码的特点是一种全宽码,即一位码元占一个单位脉冲的宽度。全宽码的优点:一是每个脉冲宽度越大,发送信号的能量就越大这对于提高接收端的信噪比有利;二是脉冲时间宽度与传输带宽成反比关系,即全宽码在信道上占用较窄的频带,并且在频谱中包含了码位的速度。
NRZ码的主要缺点是:当数据流中连续出现0 或1时,接收端很难以分辨1个信号位的开始或结束,必须采用某种方法在发送端和接收端之间提供必要的信号定时同步。同时,这种编码还会产生直流分量的积累问题,这将导致信号的失真与畸变,使传输的可靠性降低,并且由于直流分量的存在,使得无法使用一些交流耦合的线路和设备。因此,一般的数据传输系统都不采用这种编码方式。
(2) DNRZ码
DNRZ码是一种NRZ码的改进形式,它是用信号的相位变化来表示二进制数据的,一个信号位的起始处有跳变表示数据“1”,而无跳变表示数据“0”。DNRZ码不仅保持了全宽码的优点,同时提高了信号的抗干扰性和易同步性。
近年来,越来越多的高速网络系统采用了DNRZ码,成为主流的信号编码技术,在FDDI、100BASE-T及100VG-AnyLAN等高速网络中都采用了DNRZ编码。其原因是在高速网络中要求尽量降低信号的传输带宽,以利于提高传输的可靠性和降低对传输介质带宽的要求。而DNRZ编码中的码元速率与编码时钟速率相一致,具有很高的编码效率,符合高速网络对信号编码的要求。同时,为了解决数据流中连续出现0 或1时所带来的信号编码问题,通常采用两级编码方案,第一级是预编码器,对数据流进行预编码,使编码后的数据流不会出现连续 0 或连续 1,常用的预编码方法有4B5B、5B6B等;第二级是DNRZ编码,实现物理信号的传输。这种两级编码方案的编码效率可达到 80%以上。例如,在4B5B编码中,每4位数据用5位编码来表示,即4位数据就会增加 1 位的编码开销,编码效率仍为80%。
(3) 曼彻斯特码
在曼彻斯特码中,用一个信号码元中间电压跳变的相位不同来区分数据“1”和“0”,它用正的电压跳变表示“0”;用负的电压跳变表示“1”。因此,这种编码也是一种相位码。由于电压跳变都发生在每一个码元的中间,接收端可以方便地利用它作为位同步时钟,因此这种编码也称为自同步码。10Mb/s 以太网(Ethernet)采用这种曼彻斯特码。
(4) 差分曼彻斯特码
差分曼彻斯特码是一种曼彻斯特码的改进形式,其差别在于:每个码元的中间跳变只作为同步时钟信号;而数据“0”和“1”的取值是用信号位的起始处有无跳变来表示,若有跳变则为“0”;若无跳变则为“1”。这种编码的特点是每一位均用不同电平的两个半位来表示,因而始终能保持直流的平衡。这种编码也是一种自同步编码。
令牌环(Token-Ring)网采用这种差分曼彻斯特编码。
这两种曼彻斯特编码主要用于中速网络(Ethernet为 10 Mb/s;Token-Ring最高为16 Mb/s)中,而高速网络并不采用曼彻斯特编码技术。其原因是它的信号速率为数据速率的两倍,即对于 10 Mb/s的数据速率,则编码后的信号速率为 20 Mb/s,编码的有效率为 50%。对于 100 Mb/s的高速网络来说,200 Mb/s的信号速率无论对传输介质的带宽的要求,还是对传输可靠性的控制都未免太高了,将会增加信号传输技术的复杂性和实现成本,难以推广应用。因此,高速网络主要采用两级的DNRZ编码方案,而中速网络采用曼彻斯特编码方案,尽管它增加了传输所需的带宽,但在实现起来简单易行。
要实现手机端和扩展头的全双工通信,必须满足2个条件:1.信号必须在音频频率之内;2.需要是低功耗的。第一个条件限制了信号带宽,第二个条件限制了成本和功率。在这2种限制条件下,主要有2种方式实现这种同时的双向通信:FSK调制和基于曼彻斯特编码的直接数字通信。
这里主要讲解下通过数字调制中的FSK调频调制方波。FSK有2FSK(2进制调制)、4FSK(4进制调制)、8FSK(8进制调制)等等。
由于在数字系统中,使用的是0、1表示的二进制数据,在这里,我使用了2FSK来作为信号的调制。
2FSK调频调制方波的原理:用一个频率表示1,另一个不同的频率表示0。比如使用613Hz的信号代表0,1226Hz的信号代表1。如下图所示
方波可以用Cool Edit Pro工具生成,方便调试和研究。具体方法是:
打开工具,新建文件,然后会弹出下面窗口
这里根据你需求设置波形的采样率,声道和采样精度(一般是44100HZ,单声道,16位采样精度)
接下来选择菜单项-生成
你会看到如下界面,这里可以通过设置不同频率和设置调味为方波生成波形了
那么在iOS下如何接收方波解析和发送方波咧?
每段波形其实是由N(N=采样率/位持续时间(每位数据频率))个有符号的数据点组成,这些有正有负的数组成了一段段波形,比如波形0则有N个127组成的波峰波形或者N个-128组成的波底波形,而波形1则有N/2个波峰+N/2个波低组成,这个波峰波底具体数值定义可自已灵活定义,如下图所示
举个例子:比如发送个数据5,其二进制数据为0000 0101 ,这里设置采样率为44100HZ,每段波形时间频率1000HZ,定义波形为0 波峰上全是44个127,波形为0 波底上全是44个-128,波形为1的数据 半个 波峰上全是44/2个127,半个 波底上全是44/2个-128,那么5 生成波形的数据就是 0(44个127) 0 (44个-128) 0(44个127) 0 (44个-128) 0(44个127)1(44/2个-128+44/2个127)0(44个-128)1(44个127)。知道这个原理了方波解析和发送数据就简单了。
音频使用的基本步骤如下:
1.设置音频格式和采样率
mAudioFormat.mSampleRate=AUDIO_SAMPLE_RATE;//采样率
mAudioFormat.mFormatID=kAudioFormatLinearPCM;//PCM格式
mAudioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
mAudioFormat.mFramesPerPacket = 1;//每个数据包多少帧
mAudioFormat.mChannelsPerFrame = kChannels/2;//1单声道,2立体声
mAudioFormat.mBitsPerChannel = 16;//语音每采样点占用位数
mAudioFormat.mBytesPerFrame = mAudioFormat.mBitsPerChannel*mAudioFormat.mChannelsPerFrame/8;//每帧的bytes数
mAudioFormat.mBytesPerPacket = mAudioFormat.mBytesPerFrame*mAudioFormat.mFramesPerPacket;//每个数据包的bytes总数,每帧的bytes数*每个数据包的帧数
mAudioFormat.mReserved = 0;
2.设置remote io unit的渲染回调,从输入硬件获得采样传入到回调函数进行渲染,从而获得录音数据解析数据. 向回调函数填数据,从而向输出硬件提供数据进行放音发送数据.
CheckError(AudioUnitSetProperty(toneUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, disable, &mAudioFormat, sizeof(mAudioFormat)), "couldn't set the remote I/O unit's output client format");
CheckError(AudioUnitSetProperty(toneUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, enable, &mAudioFormat, sizeof(mAudioFormat)), "couldn't set the remote I/O unit's input client format");
回调函数OSStatus RenderTone(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData);通过这个回调函数就可以发送数据和解析数据
数据编码发送具体代码可参考demo里,知道了编码原理,解码对你来说就简单了
参考文档:
http://blog.csdn.net/it1988888/article/details/9073767
http://www.seeedstudio.com/wiki/index.php?title=Hijack
http://blog.csdn.net/xiejx618/article/details/9790709
iOS开发之音频口通信-通过方波来收发数据的更多相关文章
- IOS开发使用委托delegate在不同窗口之间传递数据
IOS开发使用委托delegate在不同窗口之间传递数据是本文要介绍的内容,主要是来讲解如何使用委托delegate在不同窗口之间传递数据,具体内容来看详细内容.在IOS开发里两个UIView窗口之间 ...
- iOS开发拓展篇—应用之间的跳转和数据传递
iOS开发拓展篇—应用之间的跳转和数据传 说明:本文介绍app如何打开另一个app,并且传递数据. 一.简单说明 新建两个应用,分别为应用A和应用B. 实现要求:在appA的页面中点击对应的按钮,能够 ...
- Arduino与Air800开发板使用UART通信:传输DHT22传感器数据
硬件介绍 Arduino Leonardo在数字引脚0(RX)和1(TX)进行串口通信时是使用“Serial1”,USB的串口通信使用的是“Serial”.在数字引脚0(RX)和1(TX)与USB是相 ...
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...
- IOS开发之音频--录音
前言:本篇介绍录音. 关于录音,这里提供更为详细的讲解网址:http://www.cnblogs.com/kenshincui/p/4186022.html#audioRecord ,并且该博客有更 ...
- iOS开发系列--音频播放(音效和音乐)播放本地的
音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为 点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音 ...
- iOS开发系列--音频播放、录音、
音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音频 ...
- iOS开发之音频播放AVAudioPlayer 类的介绍
主要提供以下了几种播放音频的方法: 1. System Sound Services System Sound Services是最底层也是最简单的声音播放服务,调用 AudioServicesPla ...
- iOS开发——WAVE音频文件解析
WAV文件也分了好几类,相应的非数据信息存储在文件的头部,下面简单的提一下,然后在最后重点介绍44字节的那种,一般用的都是这个. 1.8KHz采样.16比特量化的线性PCM语音信号的WAVE文件头格式 ...
随机推荐
- django 模版语法及使用
模版的定义 模版是一个文本,用语分离文档的表现形式和内容,通常用于生成html 模版当中能够使用的python语法非常少,for ,if 之类,还有ifequal,结束的时候也要写endifequal ...
- ccc let
let,其实就是块级作用域申明变量的var.之前JS的var关键字是非块级作用域的,而是函数级的. 例如arr=[0,1,2],我们经常写循环 for(var i=0,len=arr.length; ...
- 深入理解Java:注解(Annotation)基本概念
转自:http://www.cnblogs.com/peida/archive/2013/04/23/3036035.html 竹子-博客(.NET/Java/Linux/架构/管理/敏捷) 什么是注 ...
- 当编译CCBReader时出现 “ CCBAnimationManager.m Use of undeclared identifier 'other‘ ” 解决方法
第一种解决方法是去github上下载最新的CCBReader 第二种解决方法是把other替换成self.inner 建议用新版本的
- [知识点]Cantor展开
// 此博文为迁移而来,写于2015年3月14日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vtyo.html 1.含 ...
- 【BZOJ】2456: mode
http://www.lydsy.com/JudgeOnline/problem.php?id=2456 题意:给一个$n<=500000$的数列,求出现次数超过$\lfloor \frac{n ...
- 【JAVA】JAVAMail使用属性资料
核心提示:Session需要使用 java.util.Properties来构造,常用的用来构造Session的属性: mail.smtp.user SMTP的缺省用户名. mail.smtp.hos ...
- 详解SpringMVC请求的时候是如何找到正确的Controller[附带源码分析]
目录 前言 源码分析 重要接口介绍 SpringMVC初始化的时候做了什么 HandlerExecutionChain的获取 实例 资源文件映射 总结 参考资料 前言 SpringMVC是目前主流的W ...
- linux命令之 top, free,ps
linux终端查看cpu和内存使用情况 t一.op进入全屏实时系统资源使用信息查看 PID:进程的ID USER:进程所有者 PR:进程的优先级别,越小越优先被执行 NInice:值 VIRT:进程占 ...
- GO语言练习:channel select 超时机制
1.代码 2.运行 3.解析 1.代码 package main import ( "time" "fmt" ) func waitFor(ch chan in ...