之前做過的項(xiàng)目有需要通過音頻口通信用方波來收發(fā)數(shù)據(jù)帅腌,由于這方面的資料比較少枉圃,下面就介紹下其原理,希望能給大家?guī)椭?/p>
一. 音頻通信簡介
大家應(yīng)該都知道支付寶聲波支付和拉卡拉吧齐帚,它們都是利用手機(jī)的音頻口(手機(jī)耳機(jī)口)來實(shí)現(xiàn)全雙工的通信(手機(jī)與設(shè)備之間的雙向通信)。其優(yōu)點(diǎn)是低成本彼哼,編碼芯片成本低对妄,手機(jī)的 3.5mm 通信接口廣泛。
二. 市場應(yīng)用
支付寶聲波支付
手機(jī)刷卡器
皮膚檢測儀
檢測如甲醛沪羔、氣壓、溫度象浑、濕度等等
心率蔫饰、血壓等等
.......................
三. 通信原理
手機(jī)上用的耳機(jī)大多都是3.5mm的四芯座,在這四個(gè)芯中愉豺,分別是:地(GND)篓吁、左聲道(L)、右聲道(R)和線控開關(guān)(MIC)蚪拦。
左右聲道作用:向外設(shè)擴(kuò)展頭供電和發(fā)送數(shù)據(jù)
MIC作用:接收數(shù)據(jù)
市場上耳機(jī)主要有兩種標(biāo)準(zhǔn):國內(nèi)標(biāo)準(zhǔn)(如下圖所示)杖剪,國際標(biāo)準(zhǔn)(MIC和GND和國內(nèi)標(biāo)準(zhǔn)是反的,其他一樣)
聲音波形調(diào)制有調(diào)幅(AM)驰贷、調(diào)頻(FM)和調(diào)相(PM)三種盛嘿,而調(diào)制又有模擬調(diào)制和數(shù)字調(diào)制之分。(模擬調(diào)制和數(shù)字調(diào)制基本知識(shí)參考來源)
模擬調(diào)制:這種編碼方式是將數(shù)字?jǐn)?shù)據(jù)調(diào)制成模擬信號進(jìn)行傳輸括袒。通常采用三種模擬信號的載波特性(振幅次兆、頻率和相位)之一來表示被調(diào)制的數(shù)字?jǐn)?shù)據(jù),并由此產(chǎn)生三種基本調(diào)制方式锹锰。
(1) 幅移鍵控(ASK)法
ASK(Amplitude Shift Keying)是使用載波頻率的兩個(gè)不同振幅來表示兩個(gè)二進(jìn)制值芥炭。在一般情況下,用振幅恒定載波的存在與否來表示兩個(gè)二進(jìn)制字恃慧。ASK方式的編碼效率較低园蝠,容易受增益變化的影響,抗干擾性較差痢士。在音頻電話線路上彪薛,一般只能達(dá)到 1200 b/s的傳輸速率。
(2) 頻移鍵控(FSK)法
FSK(Frequency Shift Keying)是使用載波頻率附近的兩個(gè)不同頻率來表示兩個(gè)二進(jìn)制值怠蹂。FSK比ASK的編碼效率高陪汽,不易受干擾的影響,抗干擾性較強(qiáng)褥蚯。在音頻電話線路上的傳輸速率可以大于1 200 b/s挚冤。
(3) 相移鍵控(PSK)法
PSK(Phase Shift Keying)是使用載波信號的相位移動(dòng)來表示二進(jìn)制數(shù)據(jù)。在PSK方式中赞庶,信號相位與前面信號序列同相位的信號表示 0训挡,信號相位與前面信號序列反相位的信號表示 1澳骤。PSK方式也可以用于多相的調(diào)制,例如在四相調(diào)制中可把每個(gè)信號序列編碼為兩位澜薄。PSK方式具有很強(qiáng)的抗干擾能力为肮,其編碼效率比FSK還要高。在音頻線路上肤京,傳輸速率可達(dá) 9600b/s颊艳。
這些信號調(diào)制技術(shù)主要用于調(diào)制解調(diào)器(Modem)中。在實(shí)際的Modem中忘分,一般將這些基本的調(diào)制技術(shù)組合起來使用棋枕,以增強(qiáng)抗干擾能力和編碼效率。常見的組合是PSK和FSK方式的組合或者PSK和ASK方式的組合妒峦。
數(shù)字信號編碼: 對于傳輸數(shù)字信號來說重斑,最簡單的信號編碼方法是用信號的兩個(gè)不同電壓值來表示兩個(gè)二進(jìn)制數(shù)據(jù)。例如肯骇,用無電壓來表示 0窥浪,用恒定的正電壓表示 1;也可用正電壓表示 1笛丙,而用負(fù)電壓表示 0漾脂。然而,為了提高信號抗干擾能力胚鸯,并且便于信號接收同步符相,通常采用更為有效的信號編碼方法。
常用的數(shù)字信號編碼有不歸零 NRZ (Non Return to Zero)碼蠢琳、差分不歸零DNRZ 碼啊终、曼徹斯特(Manchester)碼及差分曼徹斯特(Differential Manchester)碼等。
(1) NRZ碼
NRZ碼是用信號的幅度來表示二進(jìn)制數(shù)據(jù)的傲须,通常用正電壓表示數(shù)據(jù)“1”蓝牲,用負(fù)電壓表示數(shù)據(jù)“0”,并且在表示一個(gè)碼元時(shí)泰讽,電壓均無需回到零例衍,故稱不歸零碼。NRZ碼的特點(diǎn)是一種全寬碼已卸,即一位碼元占一個(gè)單位脈沖的寬度佛玄。全寬碼的優(yōu)點(diǎn):一是每個(gè)脈沖寬度越大,發(fā)送信號的能量就越大這對于提高接收端的信噪比有利累澡;二是脈沖時(shí)間寬度與傳輸帶寬成反比關(guān)系梦抢,即全寬碼在信道上占用較窄的頻帶,并且在頻譜中包含了碼位的速度愧哟。
NRZ碼的主要缺點(diǎn)是:當(dāng)數(shù)據(jù)流中連續(xù)出現(xiàn)0 或1時(shí)奥吩,接收端很難以分辨1個(gè)信號位的開始或結(jié)束哼蛆,必須采用某種方法在發(fā)送端和接收端之間提供必要的信號定時(shí)同步。同時(shí)霞赫,這種編碼還會(huì)產(chǎn)生直流分量的積累問題腮介,這將導(dǎo)致信號的失真與畸變,使傳輸?shù)目煽啃越档投怂ィ⑶矣捎谥绷鞣至康拇嬖诘矗沟脽o法使用一些交流耦合的線路和設(shè)備。因此旅东,一般的數(shù)據(jù)傳輸系統(tǒng)都不采用這種編碼方式灭抑。
(2) DNRZ碼
DNRZ碼是一種NRZ碼的改進(jìn)形式,它是用信號的相位變化來表示二進(jìn)制數(shù)據(jù)的玉锌,一個(gè)信號位的起始處有跳變表示數(shù)據(jù)“1”名挥,而無跳變表示數(shù)據(jù)“0”疟羹。DNRZ碼不僅保持了全寬碼的優(yōu)點(diǎn)主守,同時(shí)提高了信號的抗干擾性和易同步性。
近年來榄融,越來越多的高速網(wǎng)絡(luò)系統(tǒng)采用了DNRZ碼参淫,成為主流的信號編碼技術(shù),在FDDI愧杯、100BASE-T及100VG-AnyLAN等高速網(wǎng)絡(luò)中都采用了DNRZ編碼涎才。其原因是在高速網(wǎng)絡(luò)中要求盡量降低信號的傳輸帶寬,以利于提高傳輸?shù)目煽啃院徒档蛯鬏斀橘|(zhì)帶寬的要求力九。而DNRZ編碼中的碼元速率與編碼時(shí)鐘速率相一致耍铜,具有很高的編碼效率,符合高速網(wǎng)絡(luò)對信號編碼的要求跌前。同時(shí)棕兼,為了解決數(shù)據(jù)流中連續(xù)出現(xiàn)0 或1時(shí)所帶來的信號編碼問題,通常采用兩級編碼方案抵乓,第一級是預(yù)編碼器伴挚,對數(shù)據(jù)流進(jìn)行預(yù)編碼,使編碼后的數(shù)據(jù)流不會(huì)出現(xiàn)連續(xù) 0 或連續(xù) 1灾炭,常用的預(yù)編碼方法有4B5B茎芋、5B6B等;第二級是DNRZ編碼蜈出,實(shí)現(xiàn)物理信號的傳輸田弥。這種兩級編碼方案的編碼效率可達(dá)到 80%以上。例如铡原,在4B5B編碼中皱蹦,每4位數(shù)據(jù)用5位編碼來表示煤杀,即4位數(shù)據(jù)就會(huì)增加 1 位的編碼開銷,編碼效率仍為80%沪哺。
(3) 曼徹斯特碼
在曼徹斯特碼中沈自,用一個(gè)信號碼元中間電壓跳變的相位不同來區(qū)分?jǐn)?shù)據(jù)“1”和“0”,它用正的電壓跳變表示“0”辜妓;用負(fù)的電壓跳變表示“1”枯途。因此,這種編碼也是一種相位碼籍滴。由于電壓跳變都發(fā)生在每一個(gè)碼元的中間酪夷,接收端可以方便地利用它作為位同步時(shí)鐘,因此這種編碼也稱為自同步碼孽惰。10Mb/s 以太網(wǎng)(Ethernet)采用這種曼徹斯特碼晚岭。
(4) 差分曼徹斯特碼
差分曼徹斯特碼是一種曼徹斯特碼的改進(jìn)形式,其差別在于:每個(gè)碼元的中間跳變只作為同步時(shí)鐘信號勋功;而數(shù)據(jù)“0”和“1”的取值是用信號位的起始處有無跳變來表示坦报,若有跳變則為“0”;若無跳變則為“1”狂鞋。這種編碼的特點(diǎn)是每一位均用不同電平的兩個(gè)半位來表示片择,因而始終能保持直流的平衡。這種編碼也是一種自同步編碼骚揍。
令牌環(huán)(Token-Ring)網(wǎng)采用這種差分曼徹斯特編碼字管。
這兩種曼徹斯特編碼主要用于中速網(wǎng)絡(luò)(Ethernet為 10 Mb/s;Token-Ring最高為16 Mb/s)中信不,而高速網(wǎng)絡(luò)并不采用曼徹斯特編碼技術(shù)嘲叔。其原因是它的信號速率為數(shù)據(jù)速率的兩倍,即對于 10 Mb/s的數(shù)據(jù)速率抽活,則編碼后的信號速率為 20 Mb/s硫戈,編碼的有效率為 50%。對于 100 Mb/s的高速網(wǎng)絡(luò)來說酌壕,200 Mb/s的信號速率無論對傳輸介質(zhì)的帶寬的要求掏愁,還是對傳輸可靠性的控制都未免太高了,將會(huì)增加信號傳輸技術(shù)的復(fù)雜性和實(shí)現(xiàn)成本卵牍,難以推廣應(yīng)用果港。因此,高速網(wǎng)絡(luò)主要采用兩級的DNRZ編碼方案糊昙,而中速網(wǎng)絡(luò)采用曼徹斯特編碼方案辛掠,盡管它增加了傳輸所需的帶寬,但在實(shí)現(xiàn)起來簡單易行。
要實(shí)現(xiàn)手機(jī)端和擴(kuò)展頭的全雙工通信萝衩,必須滿足2個(gè)條件:1.信號必須在音頻頻率之內(nèi)回挽;2.需要是低功耗的。第一個(gè)條件限制了信號帶寬猩谊,第二個(gè)條件限制了成本和功率千劈。在這2種限制條件下,主要有2種方式實(shí)現(xiàn)這種同時(shí)的雙向通信:FSK調(diào)制和基于曼徹斯特編碼的直接數(shù)字通信牌捷。
這里主要講解下通過數(shù)字調(diào)制中的FSK調(diào)頻調(diào)制方波墙牌。FSK有2FSK(2進(jìn)制調(diào)制)、4FSK(4進(jìn)制調(diào)制)暗甥、8FSK(8進(jìn)制調(diào)制)等等喜滨。
由于在數(shù)字系統(tǒng)中,使用的是0撤防、1表示的二進(jìn)制數(shù)據(jù)虽风,在這里,我使用了2FSK來作為信號的調(diào)制寄月。
2FSK調(diào)頻調(diào)制方波的原理:用一個(gè)頻率表示1辜膝,另一個(gè)不同的頻率表示0。比如使用613Hz的信號代表0剥懒,1226Hz的信號代表1内舟。如下圖所示
方波可以用Cool Edit Pro工具生成合敦,方便調(diào)試和研究初橘。具體方法是:
打開工具,新建文件充岛,然后會(huì)彈出下面窗口
這里根據(jù)你需求設(shè)置波形的采樣率保檐,聲道和采樣精度(一般是44100HZ,單聲道崔梗,16位采樣精度)
接下來選擇菜單項(xiàng)-生成
你會(huì)看到如下界面夜只,這里可以通過設(shè)置不同頻率和設(shè)置調(diào)味為方波生成波形了
那么在iOS下如何接收方波解析和發(fā)送方波咧?
每段波形其實(shí)是由N(N=采樣率/位持續(xù)時(shí)間(每位數(shù)據(jù)頻率))個(gè)有符號的數(shù)據(jù)點(diǎn)組成蒜魄,這些有正有負(fù)的數(shù)組成了一段段波形,比如波形0則有N個(gè)127組成的波峰波形或者N個(gè)-128組成的波底波形扔亥,而波形1則有N/2個(gè)波峰+N/2個(gè)波低組成,這個(gè)波峰波底具體數(shù)值定義可自已靈活定義谈为,如下圖所示
舉個(gè)例子:比如發(fā)送個(gè)數(shù)據(jù)5旅挤,其二進(jìn)制數(shù)據(jù)為0000 0101 ,這里設(shè)置采樣率為44100HZ,每段波形時(shí)間頻率1000HZ伞鲫,定義波形為0 波峰上全是44個(gè)127粘茄,波形為0 波底上全是44個(gè)-128,波形為1的數(shù)據(jù) 半個(gè) 波峰上全是44/2個(gè)127,半個(gè) 波底上全是44/2個(gè)-128,那么5 生成波形的數(shù)據(jù)就是 0(44個(gè)127) 0 (44個(gè)-128) 0(44個(gè)127) 0 (44個(gè)-128) 0(44個(gè)127)1(44/2個(gè)-128+44/2個(gè)127)0(44個(gè)-128)1(44個(gè)127)柒瓣。知道這個(gè)原理了方波解析和發(fā)送數(shù)據(jù)就簡單了儒搭。
音頻使用的基本步驟如下:
1.設(shè)置音頻格式和采樣率
mAudioFormat.mSampleRate=AUDIO_SAMPLE_RATE;//采樣率
mAudioFormat.mFormatID=kAudioFormatLinearPCM;//PCM格式
mAudioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
mAudioFormat.mFramesPerPacket = 1;//每個(gè)數(shù)據(jù)包多少幀
mAudioFormat.mChannelsPerFrame = kChannels/2;//1單聲道,2立體聲
mAudioFormat.mBitsPerChannel = 16;//語音每采樣點(diǎn)占用位數(shù)
mAudioFormat.mBytesPerFrame = mAudioFormat.mBitsPerChannel*mAudioFormat.mChannelsPerFrame/8;//每幀的bytes數(shù)
mAudioFormat.mBytesPerPacket = mAudioFormat.mBytesPerFrame*mAudioFormat.mFramesPerPacket;//每個(gè)數(shù)據(jù)包的bytes總數(shù)芙贫,每幀的bytes數(shù)*每個(gè)數(shù)據(jù)包的幀數(shù)
mAudioFormat.mReserved = 0;
2.設(shè)置remote io unit的渲染回調(diào),從輸入硬件獲得采樣傳入到回調(diào)函數(shù)進(jìn)行渲染,從而獲得錄音數(shù)據(jù)解析數(shù)據(jù). 向回調(diào)函數(shù)填數(shù)據(jù),從而向輸出硬件提供數(shù)據(jù)進(jìn)行放音發(fā)送數(shù)據(jù).
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");
回調(diào)函數(shù)OSStatus RenderTone(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)搂鲫;通過這個(gè)回調(diào)函數(shù)就可以發(fā)送數(shù)據(jù)和解析數(shù)據(jù)
數(shù)據(jù)編碼發(fā)送具體代碼可參考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