android音頻口通信(一)——2FSK信號調製

轉載請註明文章出處和作者!

出處:http://blog.csdn.net/xl19862005

作者:大熊(Xandy)


一、前言

    之前一直都在博客園混(地址:http://www.cnblogs.com/xl19862005),最近才搬家至CSDN,由於前幾個月剛換新工作,好久沒有更新博客了,抱歉!

    今天要和大家分享一個本人最近研發的完全具有自主知識產權的項目——android音頻口通信,並尋求有興趣的同行和友人一起合作!

    大家都知道拉卡拉,但它具體的技術實現我相信很少有人能說出來個一二,本人也正是抱着遇見問題勇往直前的技術男的精神,花了一兩個月的時間,完全摸透並已初步實現了用android手機的音頻口(耳機輸出輸入)來實現全雙工的通信,一但通信協議建立了,下面好玩的東西就多了!!

    你可以完全不再用擔心你家的電視或者空調等此類用紅外遙控的電器一時找不到遙控器而煩惱了,加上我現在研發的音頻口擴展頭,將其插入你的android手機的耳機口,裝上特製的APP,你將可以用它來遙控你家的任何帶紅外遙控功能的電器!

    你也可以拋開目前那種單調的耳機口防塵塞,加上相應的擴展頭,你將可以實時知道你周圍環境的溫度、溼度等等指標……

    諸如此類的運用,數不勝數,在這裏我就不一一列舉了,下面轉入我們的正題吧(^_^不好意思,閒話說多啦,哈哈……)

二、通信建立的基礎——耳機線上傳輸的信號

    我們知道,耳機是用來聽音樂,打電話的,既然是和聲音相關的,那麼耳機線上傳輸的就是音頻信號,常見的音頻信號一般都是在100Hz——10KHz左右的範圍內,那麼手機裏面的音頻輸出系統(DA和音頻功放)的幅頻特性(也既帶寬)一定也是在這個範圍(這是本人的猜想,由於設備和儀器有限,沒有進行系統的測試,有興趣的朋友可以用相關的測試儀器測測),那麼,既然有帶寬,好傢伙,我們就可以通過努力在這個頻帶內實現我們的通信信道了!另外值得提的一點是,耳機線上傳輸的音頻信號是交流的!

    下面我們來看看市面上常見的耳機座(公頭)的引腳定義,android手機上用的耳機大多都是3.5mm的四芯座,在這四個芯中,分別是:地、左聲道、右聲道和線控開關(MIC),而這四芯的排列常見的有如下兩種:

1、國家標準


2、國際標準

   國際標準耳機座MIC和GND和國內標準是反的,其它的一樣!

不難發現有了左右聲道,向外設擴展頭供電和發送數據就有了相應通信線路的支持,另外有了MIC這個打電話時輸入說話的信號通道,那麼手機接收數據也有了硬件通道的支持了!

三、如何調製數據

   說到信號的調製解調,很多人都會想到收音機,沒錯,收音機之所以能聽到千里之外的歌聲,正是利用了電磁波作爲傳輸媒介,將聲源的信號通過特定的調製加載到電磁波上,然後傳輸到廣闊的空間裏的,無線電的調製有調幅(AM)、調頻(FM)和調相(PM)三種,而調製又有模擬調製和數字調製之分,模擬調製就是把模擬信號(比如人說話的聲音)直接加載到電磁波上,使得電磁波的某一特性隨着聲源的變化而變化;而數字調製是近現才發展起來的,特別是DSP(沒錯,就是數字信號處理)技術的發展,數字調製中的FM有2FSK(2進制調製)、4FSK(4進制調製)、8FSK(8進制調製)等等。

   由於在數字系統中,使用的是0、1表示的二進制數據,在這裏,我使用了2FSK來作爲信號的調製。

3.1 何爲2FSK

    2FSK按字面的英語全稱是:2(binary system) Frequency-shift keying(二進制頻移鍵控),就是用二進制裏的0、1來控制載波的頻率,從而達到通信的目的!例如:我們用1ms長、1KHz的正弦信號來代表二進制裏的1;用1ms長、2KHz的正弦來代表二進制裏的0;那一連串的1KHz、2KHz的信號解調出來就是一連串的0和1,這樣是不是達到了我們想要的二進制調製的目的了?

下面我們來看一張更加形像的gif動畫圖


3.2 android下實現2FSK(純軟件調製)

   要實現2FSK,首先我們得在android系統下面獲得一個基準的正弦信號發生器,有了這個基準的正弦信號發生器,只要給它一個二進制量(0 or 1),就可改變輸出頻率,從而達到我們想要的信號調製目的。

   下面直接上圖了,經過調製後的信號輸出波形圖:(黃色的是實際輸出波型、紅色方波是我後來P上去的對應二進制數據)


    這是我定義的通信協議頭的一部分是:0x5AA5

3.3 android下音頻播放相關

    android下音頻播放的基本步驟如下:

①獲取對應音頻採樣率下的最小緩衝區的大小

  1. public static int pwMinBufferSize = AudioTrack.getMinBufferSize(EncoderCore.getPowerSupplySamplerate(), 
  2.                                 AudioFormat.CHANNEL_OUT_STEREO, 
  3.                                 AudioFormat.ENCODING_PCM_8BIT); 
public static int pwMinBufferSize = AudioTrack.getMinBufferSize(EncoderCore.getPowerSupplySamplerate(),
								AudioFormat.CHANNEL_OUT_STEREO,
								AudioFormat.ENCODING_PCM_8BIT);

②新建AudioTrack

  1. AudioTrack pwAT = new AudioTrack(AudioManager.STREAM_MUSIC, 
  2.                 EncoderCore.getPowerSupplySamplerate(), 
  3.                 AudioFormat.CHANNEL_OUT_MONO, 
  4.                 AudioFormat.ENCODING_PCM_8BIT,  
  5.                 pwMinBufferSize*2
  6.                 AudioTrack.MODE_STATIC); 
AudioTrack pwAT = new AudioTrack(AudioManager.STREAM_MUSIC,
				EncoderCore.getPowerSupplySamplerate(),
				AudioFormat.CHANNEL_OUT_MONO,
				AudioFormat.ENCODING_PCM_8BIT, 
				pwMinBufferSize*2,
				AudioTrack.MODE_STATIC);

③將緩衝區中的音頻數據寫入音頻播放線程並設置左右聲道音量等

  1. pwAT.write(carrierSignal, 0, EncoderCore.getPowerSupplyBufferSize());//寫入音頻數據 
  2.         pwAT.flush();//刷新 
  3.         pwAT.setStereoVolume(1, 0);//設置左右聲道播放音量 
  4.         pwAT.setLoopPoints(0, EncoderCore.getPowerSupplyBufferSize(), -1);//設置音頻播放循環點   
  5.         pwAT.play();//開始播放 
pwAT.write(carrierSignal, 0, EncoderCore.getPowerSupplyBufferSize());//寫入音頻數據
  		pwAT.flush();//刷新
		pwAT.setStereoVolume(1, 0);//設置左右聲道播放音量
		pwAT.setLoopPoints(0, EncoderCore.getPowerSupplyBufferSize(), -1);//設置音頻播放循環點  
		pwAT.play();//開始播放

這部分代碼是左聲道對外部擴展頭進行供電的,所以要設置循環播放,如果是發送消息就不必循環了!
    信號的調製就到這裏,下一節將分享2FSK信號的解調。

示例源碼下載地址:http://download.csdn.net/detail/xl19862005/5016843

http://blog.csdn.net/xl19862005/article/details/8522869

發佈了82 篇原創文章 · 獲贊 5 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章