① 安卓開發音頻mic口怎麼接收20khz的波形
安卓開發音頻mic口接收20khz的波形的方法?
一、手機音頻通信的特點
1、 通用性強:在智能手機普及的今天,手機的對外通信介面多種多樣,而其中以3.5mm的音頻介面通用新最強,基本所有的手機、平板電腦都會有這個介面,所以在一些要求通用性的設備上,音頻介面登上了舞台。
2、 速率低:由於手機音頻部分的采樣頻率一般為44.1KHZ(部分國產山寨為8KHZ),這極大的限制了音頻通訊的速率。我們都知道44.1KHZ的采樣頻率,那麼最高的信號頻率只能為20KHZ左右,而信號周期也不可能只有2個采樣點,通常要到10個以上,這樣層層下來通訊速率可想而知。
3、 小信號:音頻通信的信號都是毫伏級的,各個手機廠商略有不同,但通常最大不超過200mv,通常我們通信使用的信號強度也就100mv左右,這導致信號比較容易受干擾,且在開發階段對工具有著種種限制。
二、 手機音頻通信分類
1、 無線方式:
a) 無線方式大家可能不太熟悉,容我慢慢道來。我們都知道人耳能聽到的聲音頻率為20HZ~20KHZ,而手機通信的信號頻率最高也就20KHZ,所以無線通信方式是可行的。因為雖然人耳的極限聽力能到20KHZ,但普通人一般在19KHZ以上時基本就聽不到了,所以如果信號的強度比較弱,且控制在19KHZ到20KHZ之間,那麼我們就可以將之當做是「超聲波」來看待了。
b) 其實在此提到手機音頻通信的無線方式,算是給大家一種產品開發思路吧。它的通訊半徑在10M左右,前景還是很廣闊的,大家有興趣的可以試試。(其實已經有這方面的產品了)
2、 有線方式:
a) 有線方式分為單向(設備→手機)和雙向兩種,單向的限制少,開發難度也小一些,但實際應用時會受限制。而雙向通信限制多,開發難度也大一些,但實際應用時更方便些。
b) 設備→手機:曼徹斯特編碼;FSK;DTMF;自定義正弦波
c) 手機→設備:由於手機輸出的音頻信號很小,無法直接使用,要麼用運放發大到合適的范圍,要麼用電壓比較器轉換成TTL方波。
三、手機音頻通信硬體通信方式分類:手機音頻通信的硬體通信方式大體可分為方波和正弦波兩種。
1、 方波:方波通常使用的是曼徹斯特編碼方式(什麼是曼徹斯特編碼自己去查),它的好處是可以用單片機直接輸出方波,經過衰減後即可使用,方便簡單。缺點是兼容性不好,因為手機音頻部分有這樣一個特性,它只識別變化的電平信號,當麥克輸入的信號長時間保持在某一非零電平時,手機會將其視為零,而強行拉回零電位。這就是採用方波通訊方式的兼容性不好的最大原因了,並且方波也容易受干擾。
2、 正弦波:正弦波不會出現上面所說的方波的問題,故正弦波的兼容性和穩定性更好一些。通常採用方案有FSK、DTMF、信號發生器、或方波轉正弦波等。(後面會對以上方案逐一分析)
3、 通信信道分析
a) 我們知道音頻介面有4根線,MIC、地、左、右聲道。設備→手機用MIC,手機→設備用地、左、右聲道中的任意一個。這里說一下,實際產品中,有一些廠家會更換地線,即將原本左、有聲道中的一根改為地線來用,其實道理是一樣的。因為音頻通信的信號時交流信號,而地其實也是懸浮地,即便地線換了,最終的波形還是一樣的,因為最終手機解析信號時需要的是頻率和幅值。這樣還剩下一個聲道,通常被用來幫助設備進行上電識別,因為音頻通信的設備通常都是電池供電的。
b) 另外還要在MIC和地之間並聯一個4.99K的電阻,因為手機是通過檢測MIC和地之間的阻抗是否為4.99K(也有其他阻值的)來判斷是否有設備(耳機)插入,這一點要謹記。
四、各個通信方案對比分析
1、 設備→手機:
a) 曼徹斯特編碼:在諸多通信方式中,曼徹斯特編碼是最靈活簡便的一種方法,編碼信號可由單片機直接產生,經衰減電路衰減後便可直接使用。注意事項:曼徹斯特編碼信號的生成有兩種方式,一種是用PWM生成,一種是用定時器中斷翻轉IO,我個人比較傾向於定時器中斷方式。因為我們知道曼徹斯特編碼中有寬沿河窄沿之分,且寬沿和窄沿可能會靈活變化,而用PWM方式不容易精確控制寬沿、窄沿輸出的變化,而定時器中斷方式則非常靈活且容易控制。(後面會送上我自己寫的曼徹斯特編碼、解碼函數)
b) FSK、DTMF方式:FSK和DTMF兩種方式大同小異,使用時通常都是用集成的晶元來生成的,而這些晶元通常都是遵守固定的通信協議的的要求(FSK為Bell202或V.23協議,DTMF記不清名字了)。這兩種通信方式的優點是採用正弦波通信、穩定性好且使用簡便。但由於固定通信協議的限制導致通信速率、比特率也受到限制而缺乏靈活性。在這里跟他家推薦一款英國的通信晶元CMX系列,這個系列的晶元融合的FSK、DTMF的編碼、解碼,還是很不錯的,大家有興趣可以試試。(相關手冊在附件里)
c) 信號發生器、鎖相環方式:這種方式用信號發生器或者鎖相環來產生方波或正玄波,由單片機來控制波形的輸出,也可以實現音頻通信,且十分靈活。但缺點是電路較復雜,且不同頻率信號之間銜接不好掌握,用不好反而是麻煩。(相關手冊在附件里)
d) 在這里送上一種我個人認為比較好的方案:就是曼徹斯特編碼加低通濾波器,由單片機輸出曼徹斯特編碼,再經由低通濾波器將方波濾成正弦波後輸出。既解決了FSK、DTMF靈活性的問題,又解決了曼徹斯特編碼方波穩定性、通用性的問題。在低通濾波器方面我個人採用的是「集成低通開關電容濾波器」,它成本雖然高一些,但好處也是明顯的,電路簡單,使用方便,且佔用的空間亦很小。(相關手冊在附件里)
2、 手機→設備:
a) 放大電路方式:將手機輸出信號經放大電路放大到合適的幅值,然後有鎖相環或者結成FSK、DTMF晶元進行解析。該中方式難度最大,需要非常強的模擬電路功底,我個人水平有限,故採用的另一種方式。
b) 電壓比較器方式:將手機輸出的交流信號經電路強行拉到Vcc/2級別,然後加到電壓比較器一端,另一段接比較電壓Vcc/2,這樣交流信號即被轉化為TTL方波信號,此時再進行解析就變得很簡單了。
五、研發注意事項(通訊方案分析部分由於過長,放到最後來講)
1、 一個好手機錄音軟體是必須的,最好能在手機上直接看到波形的。
2、 建議用筆記本電腦進行開發,而非台式機。因為音頻信號很小,容易受干擾,而台式機干擾較大,筆記本還有一個好處是必要時可將外接電源拔掉,用電池供電。
3、 一個好錄音筆必不可少,有時需要得到純凈的音頻信號,方便更加准確的分析。
4、 做一個轉接板,一邊接音頻母座,一邊接音頻公頭,將MIC、地、左、右聲道4跟線用排陣引出,方便錄音。
5、 做一個信號衰減電路,可將設備電路產生的信號衰減至音頻介面能承受的范圍內。前期調試時,我們可以用該電路將信號錄進電腦進行信號分析。(推薦一個電腦音頻信號分析軟體:Goldwave)
6、 錄音用的音頻線切記不要太長,不然會給你帶來不少麻煩。最好自己做,用音頻裸頭、杜邦線、排陣即可製作,方便好用。
曼徹斯特編碼的編碼解碼函數如下:
/**********************************************************************
注釋:編碼函數都是採用定時器中斷的形式,以曼徹斯特編碼的窄沿作為定時器周期。
發送的數據包括1個起始位、8個數據位、1個奇偶校驗位、3個停止位。
***********************************************************************/
static void VIC_VECT_Fucton_00(void)//發送編碼數據中斷函數
{
TIMER0IS =0x0;
if((send_time%2==0) && (send_start==1))
{
switch(FSK_txState)
{
case STARTBIT:
if((GPIODATA&0x00000002)==0x00000000)//如果檢測到數據發送管腳為零
send_time++;
else
{
currentSym=0;
FSK_txState = BYTE;
}
break;
case BYTE:
if(txBit < 8)
{
currentSym = (send_byte >> txBit) & 0x01;
txBit++;
txParity += currentSym; //奇偶校驗位
}
else if (txBit == 8)
{
currentSym = txParity & 0x01; //發送奇偶校驗位
txBit++;
}
else if(txBit>8 && txBit<12)
{
// next bit is the stop bit
currentSym = 1; //發送停止位
txBit++;
}
else if(txBit == 12)
FSK_txState = STOPBIT;
break;
case STOPBIT :
txBit=0;
FSK_txState=IDLE;
send_start=0;
txParity=0;
send_byte=0;
break;
}
if(lastSym!=currentSym)
{
timer1_num++;
lastSym=currentSym;
}
}
if(timer1_num%2==0)
GPIODATA&=0xFFFFFFFD;//輸出管腳復位
else
GPIODATA|=0x00000002;//輸出管腳置位
timer1_num++;//用來控制IO口的電平翻轉
send_time++;//用來控制發送的位元組的每一位
Delay++;//Delay就是延時函數
}
/**********************************************************************
注釋:解碼函數採用外部IO中斷形式(上升沿或下降沿中斷,即電平電平跳變中斷),
用一個定時器作為時鍾,每次產生中斷時便從定時器見時間值取出,並和上一次的
記錄做差求出時間間隔,以此來判斷當前為寬沿還是窄沿。
***********************************************************************/
static void VIC_VECT_Fucton_04(void)//接受解碼數據中斷函數
{
GPIOIC|=0x00000001;//清楚上一次中斷內容
RX_time=TIMER1VALUE;
if(RX_lasttime>=RX_time)
RX_diff=RX_lasttime-RX_time; //lasttime初始值為0
else
RX_diff=65535-RX_time+RX_lasttime;
RX_lasttime=RX_time;
switch(RX_state) //啟動代碼時state已經被配置為STARTBIT
{
case STARTBIT_FALL:
if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))
{
if(RX_ones<5) //ones初始值為0
{
RX_ones = 0;
}
else
{
RX_state = DECODE; //將狀態配置為解碼
}
}
else if(RX_diff < SHORTINTERVAL)
RX_ones++;
else
RX_ones=0;
break;
case DECODE:
/**************通過間隔長短來判定數據**************/
if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))// 若間距在范圍內則當前數據位值和前一個相反
{
currentbit=(currentbit+1)&0x01;
RX_times+=2;
}
else if( RX_diff < SHORTINTERVAL)
{
currentbit=currentbit;
RX_times++;
}
else
RX_state = DATAINIT;
/****************接受數據位,從低位接起****************/
if(RX_times%2==0)
{
if(RX_bitcounter<8)
{
if (currentbit==1)
{
uartByteRx = (uartByteRx >> 1) + (1<<7);
rxParity++; //奇偶校驗位
RX_bitcounter++; //接受數據位數
}
else
{
uartByteRx = (uartByteRx >> 1);
RX_bitcounter++;
}
}
else
{
rxParity&=0x01; //進行奇偶校驗
if(rxParity==currentbit)
{
RX_bitcounter++;
RX_finish=1;
RX_state=DATAINIT;
}
else
RX_state=DATAINIT; //若奇偶校驗錯誤則,重新檢測
}
}
break;
case DATAINIT : //初始化參數狀態
RX_bitcounter=0;
RX_ones=0;
rxParity=0;
currentbit=0;
RX_state=STARTBIT_FALL;
RX_times=0;
break;
default:
break;
}
}
② 如何在Android平台上使用USB Audio設備
Android對USB的支持有兩種模式:
HOST模式:Android設備為USB匯流排和外設供電,數據傳輸是雙向的。
Accessory模式:即附件模式,Android作為附件,手機和電腦連接,通常是這種模式,由USB Device端向匯流排供電,數據傳輸方向是雙向的。這就是為什麼手機插到電腦上可以充電的原因。
在討論具體代碼之前,需要先講一下再host模式下面的調試辦法,因為數據線的埠被外設使用了,那麼,傳統的連接數據線調試的方法已經不行了。官網給出了解決辦法:
1、請把Android設備用數據線連接到電腦,當然,也要把Android設備的wifi打開。
2、在windows命令行下,進入SDK platform-tools/ 目錄(具體看SDK安裝在哪個目錄了),執行 adb tcpip 5555 回車。這里其實是打開了adb調試的無線埠(Android設備在電腦上的埠映射),其實後面的數字可以隨便來,只要埠沒有被佔用。
3、adb connect <device-ip-address>:5555鍵入回車,這里的device-ip-address是Android端的IP地址。
4、最後adb usb回車,假如沒有問題,現在已經可以在eclipse上看到logcat的輸出了。
其實還有個簡單的辦法,可以在應用商店上下一個無線ADB工具,隨便哪個都可以,這類工具就是在Android端做了上面的那些工作,而且還不用連數據線,但是第三步的那個操作還是要在windows的命令行窗口手動輸入的。