[前言]
前言
今天跟王總聊天,他狠狠地(形容詞)叼了我,他說(shuō)你為什么不寫一些比較牛逼的文章,為什么總是寫一些教別人如何安裝軟件,如何打開軟件的文章,你還妄想用這樣的文章拉攏人心,你是不是腦子進(jìn)水,是不是腦子進(jìn)水,是不是腦子進(jìn)水,王總連續(xù)說(shuō)了幾次腦子進(jìn)水,我當(dāng)時(shí)是羞愧萬(wàn)分,我不知道如何去表達(dá)我當(dāng)時(shí)的窘境,我只能默默的低頭跟王總說(shuō),我水平太差,我水平太差,我水平太差,然后王總又跟我說(shuō)當(dāng)時(shí)他在華為做開發(fā),linux相關(guān)的問(wèn)題從不過(guò)夜,一年升一個(gè)級(jí)別,我們?cè)谟淇斓慕徽勚薪Y(jié)束了午飯時(shí)間,所以我想了很久,有必要結(jié)合AI音箱寫一下Android音頻方面的知識(shí)
最近音頻方面的開發(fā)非常火熱,也出現(xiàn)了一些非常牛逼的公司,訊飛占領(lǐng)老大位置,思必馳,云之聲都有非常完善的AI音箱方案
對(duì)應(yīng)的產(chǎn)品有,小愛音箱,小度,叮咚,天貓精靈,斐訊,市場(chǎng)一片火熱,做好一個(gè)AI音箱,電聲方面的知識(shí)是必不可少的,我這篇文章主要也是從這個(gè)為入口講一些這方面的知識(shí)。
一、音頻基礎(chǔ)
(1)采樣率(samplerate)
采樣就是把模擬信號(hào)數(shù)字化的過(guò)程,不僅僅是音頻需要采樣,所有的模擬信號(hào)都需要通過(guò)采樣轉(zhuǎn)換為可以用0101來(lái)表示的數(shù)字信號(hào),示意圖如下所示:
藍(lán)色代表模擬音頻信號(hào),紅色的點(diǎn)代表采樣得到的量化數(shù)值。采樣頻率越高,紅色的間隔就越密集,記錄這一段音頻信號(hào)所用的數(shù)據(jù)量就越大,同時(shí)音頻質(zhì)量也就越高。
根據(jù)奈奎斯特理論,采樣頻率只要不低于音頻信號(hào)最高頻率的兩倍,就可以無(wú)損失地還原原始的聲音。
通常人耳能聽到頻率范圍大約在20Hz~20kHz之間的聲音,為了保證聲音不失真,采樣頻率應(yīng)在40kHz以上。常用的音頻采樣頻率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。
(2)量化精度(位寬)
上圖中,每一個(gè)紅色的采樣點(diǎn),都需要用一個(gè)數(shù)值來(lái)表示大小,這個(gè)數(shù)值的數(shù)據(jù)類型大小可以是:4bit、8bit、16bit、32bit等等,位數(shù)越多,表示得就越精細(xì),聲音質(zhì)量自然就越好,當(dāng)然,數(shù)據(jù)量也會(huì)成倍增大。
常見的位寬是:8bit 或者 16bit
(3)聲道數(shù)(channels)
由于音頻的采集和播放是可以疊加的,因此,可以同時(shí)從多個(gè)音頻源采集聲音,并分別輸出到不同的揚(yáng)聲器,故聲道數(shù)一般表示聲音錄制時(shí)的音源數(shù)量或回放時(shí)相應(yīng)的揚(yáng)聲器數(shù)量。單聲道(Mono)和雙聲道(Stereo)比較常見,顧名思義,前者的聲道數(shù)為1,后者為2
二、Android Audio框架
Android用的是C/S的框架,就是一個(gè)client,一個(gè)service,中間是一個(gè)HAL作為統(tǒng)一的接口,HAL往下就會(huì)到tinyalsa,tinyalsa是alsa的裁剪版本,后面對(duì)應(yīng)的就是驅(qū)動(dòng)層了。
三、I2S接口介紹
I2S總線標(biāo)準(zhǔn):I2S(Inter-IC Sound Bus)是飛利浦公司為數(shù)字音頻設(shè)備之間的音頻數(shù)據(jù)傳輸而制定的一種總線標(biāo)準(zhǔn)。在飛利浦公司的I2S標(biāo)準(zhǔn)中,既規(guī)定了硬件接口規(guī)范,也規(guī)定了數(shù)字音頻數(shù)據(jù)的格式。I2S有3個(gè)主要信號(hào):
串行時(shí)鐘 SCLK:也叫做位時(shí)鐘BCLK,即對(duì)應(yīng)數(shù)字音頻的每一位數(shù)據(jù),SCLK的頻率=2×采樣頻率×采樣位數(shù),現(xiàn)在問(wèn)題來(lái)了,有人會(huì)問(wèn)這些東西到底是什么意思呢?其實(shí),I2S一般是傳輸立體聲,有兩個(gè)聲道channel,采樣頻率指得是采樣數(shù)率,多久去采集一個(gè)點(diǎn),每個(gè)點(diǎn)是幾個(gè)bit組成。
幀時(shí)鐘LRCK:用于切換左右聲道的數(shù)據(jù),LRCK為“0”表示正在傳輸?shù)氖亲舐暤赖臄?shù)據(jù),為“1”表示正在傳輸?shù)氖怯衣暤赖臄?shù)據(jù)。LRCLK == FS,就是采樣頻率
串行數(shù)據(jù)SDATA:就是用二進(jìn)制補(bǔ)碼表示的音頻數(shù)據(jù),有時(shí)為了使系統(tǒng)間能夠更好的同步,還需要另外傳輸一個(gè)信號(hào)MCLK,稱為主時(shí)鐘,也叫系統(tǒng)時(shí)鐘(System Clock),是采樣頻率的256或384倍
I2S不同的標(biāo)準(zhǔn)介紹:I2S主要是針對(duì)ADC和主控,如果ADC設(shè)置的I2S標(biāo)準(zhǔn)和主控的不一致,那么錄音肯定是要出問(wèn)題的,正常使用的時(shí)候,會(huì)涉及1bit delay,大家在量I2S波形的時(shí)候也可以看出來(lái)
BCLK計(jì)算:BCLK =LRCLKxbitsxch,Ch 默認(rèn)是2,我們現(xiàn)在用的是8ch的數(shù)據(jù),但是我們用的是4個(gè)數(shù)據(jù)線,這時(shí)候計(jì)算的時(shí)候ch還是用2來(lái)計(jì)算
BCLK =16K x 32bitsx2ch = 1.024M
注意:我們?cè)谑褂肅X20810 ADC芯片的時(shí)候,CX20810現(xiàn)在是市面上做AI音響用的主流芯片,像叮咚叮咚就是用這個(gè),里面介紹一個(gè)TDM 模式,這個(gè)也是一個(gè)I2S的標(biāo)準(zhǔn),不過(guò)這個(gè)標(biāo)準(zhǔn)是一個(gè)DATA線傳8ch的數(shù)據(jù)
四、TINYALSA子系統(tǒng)
(1)代碼介紹
目前l(fā)inux中主流的音頻體系結(jié)構(gòu)是ALSA(Advanced Linux Sound Architecture),ALSA在內(nèi)核驅(qū)動(dòng)層提供了alsa-driver,在應(yīng)用層提供了alsa-lib,應(yīng)用程序只需要調(diào)用alsa-lib(libtinyalsa.so)提供的API就可以完成對(duì)底層硬件的操作。說(shuō)的這么好,但是Android中沒有使用標(biāo)準(zhǔn)的ALSA,而是一個(gè)ALSA的簡(jiǎn)化版叫做tinyalsa。Android中使用tinyalsa控制管理所有模式的音頻通路,我們也可以使用tinyalsa提供的工具進(jìn)行查看、調(diào)試。
tinycap.c 實(shí)現(xiàn)錄音相關(guān)代碼 tinycap
Tinyplay.c 實(shí)現(xiàn)放音相關(guān)代碼 tinyplay
Pcm.c 與驅(qū)動(dòng)層alsa-driver調(diào)用接口,為audio_hw提供api接口
Tinymix 查看和設(shè)置混音器 tinymix
Tinypcminfo.c 查看聲卡信息tinypcminfo
(2)音頻幀(frame)
這個(gè)概念在應(yīng)用開發(fā)中非常重要,網(wǎng)上很多文章都沒有專門介紹這個(gè)概念。
音頻跟視頻很不一樣,視頻每一幀就是一張圖像,而從上面的正玄波可以看出,音頻數(shù)據(jù)是流式的,本身沒有明確的一幀幀的概念,在實(shí)際的應(yīng)用中,為了音頻算法處理/傳輸?shù)姆奖悖话慵s定俗成取2.5ms~60ms為單位的數(shù)據(jù)量為一幀音頻。
這個(gè)時(shí)間被稱之為“采樣時(shí)間”,其長(zhǎng)度沒有特別的標(biāo)準(zhǔn),它是根據(jù)編解碼器和具體應(yīng)用的需求來(lái)決定的,我們可以計(jì)算一下一幀音頻幀的大小:
假設(shè)某音頻信號(hào)是采樣率為8kHz、雙通道、位寬為16bit,20ms一幀,則一幀音頻數(shù)據(jù)的大小為:
int size = 8000 x 2 x 16bit x 0.02s = 5120bit = 640 byte
音頻幀總結(jié)
period(周期):硬件中斷間的間隔時(shí)間。它表示輸入延時(shí)。
聲卡接口中有一個(gè)指針來(lái)指示聲卡硬件緩存區(qū)中當(dāng)前的讀寫位置。只要接口在運(yùn)行,這個(gè)指針將循環(huán)地指向緩存區(qū)中的某個(gè)位置。
frame size=sizeof(one sample) * nChannels
alsa中配置的緩存(buffer)和周期(size)大小在runtime中是以幀(frames)形式存儲(chǔ)的。
period_bytes=pcm_format_to_bits 用來(lái)計(jì)算一個(gè)幀有多少bits,實(shí)際應(yīng)用的時(shí)候經(jīng)常用到
下面有個(gè)老外的講的音頻幀,很多解釋都是從這里翻譯來(lái)的,大家自行體味一下
五、CODEC介紹
(1)專用術(shù)語(yǔ)
ASLA- Advanced Sound Linux Architecture
OSS - 以前的Linux音頻體系結(jié)構(gòu),被ASLA取代并兼容
Codec - Coder/Decoder
I2S/PCM/AC97 - Codec與CPU間音頻的通信協(xié)議/接口/總線
DAI- Digital Audio Interface 其實(shí)就是I2S/PCM/AC97
DAC - Digit to Analog Conversion
ADC - Analog to Digit Conversion
DSP - Digital Signal Processor
Mixer - 混音器,將來(lái)自不同通道的幾種音頻模擬信號(hào)混合成一種模擬信號(hào)
Mute - 消音,屏蔽信號(hào)通道
PCM - Pulse Code Modulation 脈沖調(diào)制編碼,一種從音頻模擬信號(hào)轉(zhuǎn)換成數(shù)字信號(hào)的技術(shù),區(qū)別于PCM音頻通信協(xié)議
SSI - Serial Sound Interface
DAPM - Dynamic Audio Power Management
(2)放音錄音框圖
(3) OSS和ALSA比較
a.OSS的優(yōu)點(diǎn)(對(duì)用戶來(lái)說(shuō))
在內(nèi)核空間(kernel space)里面包含了一個(gè)透明軟件混音器(vmix)。這樣多個(gè)程序就可以同時(shí)使用聲音設(shè)備而且沒有任何問(wèn)題。
這個(gè)混音器可以讓你單獨(dú)調(diào)節(jié)各個(gè)程序的音量。
對(duì)某些老聲卡有著更好的支持比如創(chuàng)新(Creative)的X-Fi。
聲音程序的初始反應(yīng)時(shí)間一般更好。
對(duì)使用OSS的應(yīng)用程序接口(API)的程序有更好的支持,很多程序都支持OSS的API,而不需要ALSA的模擬。
b.OSS的優(yōu)點(diǎn)(對(duì)開發(fā)者來(lái)說(shuō))
清晰的API文檔,更易于使用。
支持用戶空間的聲音驅(qū)動(dòng)。
可移植性強(qiáng),OSS也可以在BSDs和Solaris下運(yùn)行。
本身可以跨平臺(tái),可以更方便移植到新的操作系統(tǒng)。
c.ALSA的優(yōu)點(diǎn)
ALSA對(duì)USB音頻設(shè)備支持更好,而OSS的輸出還在試驗(yàn)中,輸入還未實(shí)現(xiàn)。
ALSA支持藍(lán)牙聲音設(shè)備。
ALSA支持AC'97和HDAudio dial-up soft-modems (比如Si3055)。
ALSA對(duì)MIDI支持得更好,但用OSS你只能通過(guò)軟件合成器(如timidity和fluidsynth)來(lái)使用MIDI。
ALSA對(duì)待機(jī)支持更好,而用OSS,你需要在待機(jī)前使用soundoff來(lái)停止OSS驅(qū)動(dòng),在恢復(fù)后使用soundon來(lái)啟動(dòng)OSS。
OSS的jack檢測(cè)目前在某些HDAudio-powered主板上不能正常工作。也就是說(shuō)在某些型號(hào)的主板上,你可能需要在插入耳機(jī)的時(shí)候手動(dòng)關(guān)閉外置揚(yáng)聲器。而ALSA沒這個(gè)問(wèn)題。
d.調(diào)用接口
alsa是多了一個(gè)alsa-lib接口,但是OSS是直接操作設(shè)備文件的,這個(gè)差異還是很大的,不過(guò)幸運(yùn)的是,alsa出來(lái)后為了兼容oss,也是做了一些修改。
(4)ASOC介紹
ASOC--ALSA System on Chip (即ALSA在片選系統(tǒng)上的應(yīng)用),是建立在標(biāo)準(zhǔn)ALSA驅(qū)動(dòng)層上,為了更好地支持嵌入式處理器和移動(dòng)設(shè)備中的音頻Codec的一套軟件體系。在ASoc出現(xiàn)之前,內(nèi)核對(duì)于SoC中的音頻已經(jīng)有部分的支持,不過(guò)會(huì)有一些局限性
Codec類: Codec即編解碼芯片的驅(qū)動(dòng),此Codec驅(qū)動(dòng)是和平臺(tái)無(wú)關(guān),包含的功能有: 音頻的控制接口,音頻讀寫IO接口,以及DAPM的定義等。如果需要的話,此Codec類可以在BT,F(xiàn)M,MODEM模塊中不做修改的使用。因此Codec就是一個(gè)可重復(fù)使用的模塊,同一個(gè)Codec在不同的SOC中可以使用。對(duì)應(yīng)ak7755.c
Platform類: 可以理解為某款SOC平臺(tái),平臺(tái)驅(qū)動(dòng)中包括音頻DMA引擎驅(qū)動(dòng),數(shù)字接口驅(qū)動(dòng)(I2S, AC97, PCM)以及該平臺(tái)相關(guān)的任何音頻DSP驅(qū)動(dòng)。同樣此Platform也可以重用,在不同的Machine中可以直接重復(fù)使用。
Machine類:Machine可以理解為是一個(gè)橋梁,用于在Codec和Platform之間建立聯(lián)系。此Machine指定了該機(jī)器使用那個(gè)Platform,那個(gè)Codec,最終會(huì)通過(guò)Machine建立兩者之間的聯(lián)系。
(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
六、音頻相關(guān)調(diào)試技巧
在調(diào)試錄音和放音的時(shí)候,我們先使用tinyalsa的調(diào)試命令來(lái)進(jìn)行調(diào)試,比如tinycap、tinyplay、tinypcminfo
Proc下的音頻調(diào)試介紹:
#The_.2Fproc.2Fasound.2Foss.2F_directory
(1)通過(guò)命令確認(rèn)聲卡是否注冊(cè)成功
rk3399_mid:/ $ ls /proc/asound/
card0 cards hwdep rockchipak7755c timers
card1 devices pcm rockchipi2sdmic version
$ ls /dev/snd/
(2)xrun debug
我們?cè)谡{(diào)試音頻的時(shí)候,難免會(huì)遇到underrun或者overrun,出現(xiàn)此兩者情況時(shí)內(nèi)核會(huì)打印log協(xié)助問(wèn)題分析,Menuconfig中需要開啟如下選項(xiàng):
[*] Advanced Linux Sound Architecture --->
[*] Debug [*] More verbose debug
[*] Enable PCM ring buffer overrun/underrun debugging
然后在對(duì)應(yīng)聲卡/proc/asound/card0/xrun中寫入相應(yīng)的值,值如下:
#define XRUN_DEBUG_BASIC (1 xrun
開啟所有debug信息檢測(cè)。
Xrun主要是讀寫速度不一致引起的音頻錄音播放異常,之前遇到一個(gè)這樣的問(wèn)題是因?yàn)镈MA引起的,在注冊(cè)聲卡設(shè)備時(shí)會(huì)申請(qǐng)一個(gè)period_size,這個(gè)size是不能隨意更改大小的,所以大家在寫代碼的時(shí)候要注意。
七、AI智能音響核心點(diǎn)
這部分講的每一點(diǎn)內(nèi)容都是非常核心的,直接影響到AI音箱的整體效果,包括聲源定位,回聲消除,有很多人反饋為什么我的音箱聲源定位不好,為什么我的回聲消除效果很差,我們就要從下面幾個(gè)問(wèn)題點(diǎn)去排查
(1)、音頻部分
1、做到有效采樣16bits 32bits,(失真、截幅)、軟件端對(duì)多通道數(shù)據(jù)可以編碼
多通道數(shù)據(jù)采樣同步,采樣率同步,采樣時(shí)鐘同步,比如不能出現(xiàn)錄音的時(shí)候出現(xiàn)失真情況。
2、錄音的采樣深度理論是越大是越好的,采樣頻率要跟算法部分確認(rèn)好,訊飛要求的是16K的采樣音頻送給他們的算法
3、播放不能有失真,電聲部分一定要通過(guò)嚴(yán)格的測(cè)試要求,整個(gè)掃頻階段都不能出現(xiàn)問(wèn)題,比如不能出現(xiàn)播放高頻的時(shí)候發(fā)現(xiàn)喇叭有低頻的聲音此類問(wèn)題
(2)、結(jié)構(gòu)部分
1、MIC開孔深度、孔徑、構(gòu)型符合標(biāo)準(zhǔn);
2、內(nèi)部音腔隔離,密封性能;
3、結(jié)構(gòu)震動(dòng)隔離;震音非常關(guān)鍵,測(cè)試的時(shí)候會(huì)發(fā)現(xiàn),裝上機(jī)構(gòu)后的回聲消除比沒有結(jié)構(gòu)時(shí)候差很多,大多是由于增加了結(jié)構(gòu),震音結(jié)構(gòu)影響很大。
4、喇叭與MIC的距離,不能太近;
(3)、回聲消除注意
作用:
抑制產(chǎn)品(喇叭)本身發(fā)出的聲音,使得產(chǎn)品在播放音頻時(shí)依然可以進(jìn)行語(yǔ)音交互;
注意點(diǎn):
1、需要接參考信號(hào),信號(hào)采樣需要符合要求;
做到有效采樣
使用硬采集方案
參考信號(hào)采樣盡量與mic采集到的回聲同步,至少不晚于回聲;
2、結(jié)構(gòu)方面需要特別注意;
內(nèi)部音腔隔離
震動(dòng)隔離
喇叭與MIC的相對(duì)位置;
3、硬件選型方面需要注意;
4、整個(gè)采樣系統(tǒng)中的延時(shí)要穩(wěn)定;
彩蛋:
?ASR(automaticspeech recognition)把語(yǔ)音轉(zhuǎn)換成文字,AI算法說(shuō)的是自我學(xué)習(xí)算法,所以學(xué)習(xí)是一個(gè)非常復(fù)雜的過(guò)程,下面是一個(gè)鏈接,有開源的一些模型,感興趣的可以自己拿去學(xué)習(xí)
https://github.com/kaldi-asr/kaldi