一、數(shù)字音頻背景
1.1 數(shù)字音頻簡(jiǎn)介
聲音在自然界以聲波的形式存在,是一系列連續(xù)變化的模擬信號(hào),聲音的三個(gè)要素是音調(diào)、音強(qiáng)和音色。聲波有三個(gè)重要參數(shù):頻率 ω0、幅度A n 和相位ψn ,這也就決定了音頻信號(hào)的特征。根據(jù)聲波的特征,可把音頻信息分類為規(guī)則音頻和不規(guī)則聲音。其中規(guī)則音頻又可以分為語(yǔ)音、音樂和音效。音頻信號(hào)是(Audio)帶有語(yǔ)音、音樂和音效的有規(guī)律的聲波的頻率、幅度變化信息載體。
1.1.1 數(shù)字音頻
數(shù)字音頻是一種利用數(shù)字化手段對(duì)聲音進(jìn)行錄制、存放、編輯、壓縮或播放的技術(shù),它是隨著數(shù)字信字音頻號(hào)處理技術(shù)、計(jì)算機(jī)技術(shù)、多媒體技術(shù)的發(fā)展而形成的一種全新的聲音處理手段。數(shù)字音頻計(jì)算機(jī)數(shù)據(jù)的存儲(chǔ)是以0、1的形式存取的,那么數(shù)字音頻就是首先將音頻文件轉(zhuǎn)化,接著再將這些電平信號(hào)轉(zhuǎn)化成二進(jìn)制數(shù)據(jù)保存,播放的時(shí)候就把這些數(shù)據(jù)轉(zhuǎn)換為模擬的電平信號(hào)再送到喇叭播出,數(shù)字聲音和一般磁帶、廣播、電視中的聲音就存儲(chǔ)播放方式而言有著本質(zhì)區(qū)別。相比而言,它具有存儲(chǔ)方便、存儲(chǔ)成本低廉、存儲(chǔ)和傳輸?shù)倪^程中沒有聲音的失真、編輯和處理非常方便等特點(diǎn)。
1.1.2 數(shù)字音頻文件
數(shù)字音頻文件是通過聲音錄入設(shè)備錄制的原始聲音,直接記錄了真實(shí)聲音的二進(jìn)制采樣數(shù)據(jù),有些文件并對(duì)原始數(shù)據(jù)進(jìn)行了頻率過濾和存儲(chǔ)格式壓縮,音頻文件格式主要分有損和無損兩類。有損文件格式是基于聲學(xué)心理學(xué)的模型,除去人類很難或根本聽不到的聲音。
無損格式如:PCM,WAV,ALS,ALAC,TAK,F(xiàn)LAC,APE,WavPack(WV) ;
有損格式如:MP3,AAC,WMA,Ogg ;
數(shù)字音頻文件幾個(gè)重要參數(shù):采樣頻率、量化位寬、聲道數(shù)。
1.1.3 采樣頻率
采樣頻率是指將模擬聲音波形進(jìn)行數(shù)字化時(shí),每秒鐘抽取聲波幅度樣本的次數(shù)。采樣頻率的選擇應(yīng)該遵循奈奎斯特(Harry Nyquist)采樣理論:如果對(duì)某一模擬信號(hào)進(jìn)行采樣,則采樣后可還原的最高信號(hào)頻率只有采樣頻率的一半,或者說只要采樣頻率高于輸入信號(hào)最高頻率的兩倍,就能從采樣信號(hào)系列重構(gòu)原始信號(hào)。正常人聽覺的頻率范圍大約在20Hz~20kHz之間,根據(jù)奈奎斯特采樣理論,為了保證聲音不失真,采樣頻率應(yīng)該在40kHz左右,常用的采樣率有:
8,000 Hz - 電話所用采樣率,對(duì)于人的說話已經(jīng)足夠;
11,025 Hz ;
22,050 Hz - 無線電廣播所用采樣率;
32,000 Hz - miniDV 數(shù)碼視頻camcorder、DAT(LP mode)所用采樣率;
44,100 Hz - 音頻CD,也常用于MPEG-1音頻(VCD, SVCD, MP3)所用采樣率;
47,250 Hz - 商用 PCM 錄音機(jī)所用采樣率;
48,000 Hz - miniDV、數(shù)字電視、DVD、DAT、電影和專業(yè)音頻所用的數(shù)字聲音所用采樣率;
50,000 Hz - 商用數(shù)字錄音機(jī)所用采樣率;
96,000或192,000Hz - DVD Audio、一些LPCMDVD音軌、BD-OM(藍(lán)光盤)音軌、和HDDVD(高清晰度DVD)音軌所用所用采樣率;
2.8224 MHz - Direct Stream Digital的1位sigma-delta modulation過程所用采樣率。
1.1.4 量化位寬
量化位寬是對(duì)模擬音頻信號(hào)的幅度進(jìn)行數(shù)字化,它決定了模擬信號(hào)數(shù)字化以后的動(dòng)態(tài)范圍,常用的有8位、12位、16位、24位和32位。量化位越高,信號(hào)的動(dòng)態(tài)范圍越大,數(shù)字化后的音頻信號(hào)就越可能接近原始信號(hào),但所需要的存貯空間也越大。
1.1.5 聲道數(shù)
聲道數(shù)是反映音頻數(shù)字化質(zhì)量的另一個(gè)重要因素,聲道技術(shù)已廣泛運(yùn)用于各類傳統(tǒng)影院和家庭影院中:
單聲道的聲道數(shù)為1個(gè)聲道;
雙聲道的聲道數(shù)為2個(gè)聲道,立體聲道的聲道數(shù)默認(rèn)為2個(gè)聲道;
四聲道環(huán)繞規(guī)定了4個(gè)發(fā)音點(diǎn):前左、前右,后左、后右,4.1聲道音箱系統(tǒng)其中“.1”聲道,則是一個(gè)專門設(shè)計(jì)的超低音聲道,這一聲道可以產(chǎn)生頻響范圍20~120Hz的超低音;
5.1聲音系統(tǒng)其實(shí)來源于4.1環(huán)繞,不同之處在于它增加了一個(gè)中置單元。這個(gè)中置單元負(fù)責(zé)傳送低于80Hz的聲音信號(hào),在欣賞影片時(shí)有利于加強(qiáng)人聲,把對(duì)話集中在整個(gè)聲場(chǎng)的中部,以增加整體效果;
7.1系統(tǒng)已經(jīng)出現(xiàn),它在5.1的基礎(chǔ)上又增加了中左和中右兩個(gè)發(fā)音點(diǎn),以求達(dá)到更加完美的境界。
1.2 linux音頻子系統(tǒng)介紹
Linux音頻系統(tǒng)比較復(fù)雜,各層間有很多交叉,可能是最無序的子系統(tǒng),并且它有兩套音頻驅(qū)動(dòng)框架: OSS (Open Sound System)和ALSA (Advanced Linux Sound Architechture),所以底層驅(qū)動(dòng)有OSS和ALSA兩套API。ALSA經(jīng)過多年的發(fā)展,基本統(tǒng)一了Linux聲卡硬件驅(qū)動(dòng)層的接口,OSS日漸退出,但是在ALSA之上的各個(gè)應(yīng)用層,方案和軟件繁多復(fù)雜,ESD,PulseAudio, JACK,GStreamer, 這些系統(tǒng)組件各個(gè)為戰(zhàn),實(shí)現(xiàn)了不同的功能。
圖1.2
上圖1.2描述了Linux音頻系統(tǒng)各部分調(diào)用關(guān)系,下面簡(jiǎn)要介紹各部分。
1.2.1 ALSA和OSS
ALSA 是 Advanced Linux Sound Architecture 的縮寫,即高級(jí) Linux聲音架構(gòu),在 Linux 操作系統(tǒng)上提供了對(duì)音頻和 MIDI(Musical InstrumentDigital Interface,音樂設(shè)備數(shù)字化接口)的支持。在 Linux2.6 版本內(nèi)核以后,ALSA 已經(jīng)成為默認(rèn)的聲音子系統(tǒng),用來替換 2.4 版本內(nèi)核中的OSS(Open Sound System,開放聲音系統(tǒng))。
ALSA 是一個(gè)完全開放源碼的音頻驅(qū)動(dòng)程序集,是由志愿者維護(hù)的開源項(xiàng)目,而 OSS 則是由公司提供的商業(yè)產(chǎn)品。ALSA 系統(tǒng)包括驅(qū)動(dòng)包alsa-driver(集成在內(nèi)核源碼),開發(fā)包 alsa-libs,開發(fā)包插件 alsalibplugins,設(shè)置管理工具包 alsa-utils,其他聲音相關(guān)處理小程序包alsa-tools,特殊音頻固件支持包 alsa-firmware,OSS 接口兼容模擬層工具 alsa-oss 共 7 個(gè)子項(xiàng)目,其中只有 alsa-driver 是必須的。
1.2.2 FFADO
很多專業(yè)音樂設(shè)備都是通過“火線”連接到pc的。FFADO項(xiàng)目旨在通過提供一個(gè)通用的火線上,支持基于Linux平臺(tái)的開源音頻設(shè)備解決方案。FFADO項(xiàng)目是的FreeBOB項(xiàng)目的繼任者。FFADO在志愿者為基礎(chǔ)的社區(qū)的努力下,試圖提供Linux至少是存在于其他操作系統(tǒng)功能相同的水平,并且希望支持的火線音頻設(shè)備的范圍非常廣泛:從混合音頻控制設(shè)備到DSP算法設(shè)備的純音頻接口。然而,能夠支持的是設(shè)備供應(yīng)商的合作。優(yōu)先考慮提供信息和測(cè)試設(shè)備的制造商。
FFADO另一個(gè)特性是整合了dsp芯片的混音驅(qū)動(dòng),你可以通過圖形界面設(shè)置輸入輸出,以及音效等。不同于alsa的軟混音,你可以真正的對(duì)硬件進(jìn) 行控制,做到真正的0延時(shí),這對(duì)現(xiàn)場(chǎng)錄音等需求大大有助。和alsa等其他架構(gòu)不同,jack僅僅對(duì)其支持的硬件進(jìn)行處理,沒有對(duì)alsa或者pulse提供接口,除非你用alsa替代jack,否則你無 法使用jack正常的進(jìn)行音頻播放。但是很多專業(yè)設(shè)備對(duì)jack支持良好,所以jack是你的最優(yōu)選擇。
1.2.3 PulseAudio
PulseAudio是內(nèi)置POSIX的操作系統(tǒng)是一個(gè)完善的機(jī)制,它是聲音的應(yīng)用程序代理。它允許應(yīng)用程序和硬件之間傳遞聲音數(shù)據(jù)上的高級(jí)操作。諸如將音頻傳輸?shù)讲煌臋C(jī)器、改變采樣格式或通道計(jì)數(shù)以及將多個(gè)聲音混合成一個(gè),這些都很容易使用聲音服務(wù)器實(shí)現(xiàn)。內(nèi)置專為L(zhǎng)inux系統(tǒng)。它也被移植到Solaris、FreeBSD,NetBSD,MacOS X的測(cè)試,Windows 2000和Windows XP。內(nèi)置是所有有關(guān)linux系統(tǒng)的一個(gè)組成部分,用于由多個(gè)供應(yīng)商的各種移動(dòng)設(shè)備。
1.2.4 GStreamer
GStreamer是一個(gè)開源的多媒體框架庫(kù)。利用它,可以構(gòu)建一系列的媒體處理模塊,包括從簡(jiǎn)單的ogg播放功能到復(fù)雜的音頻(混音)和視頻(非線性編輯)的處理。應(yīng)用程序可以透明的利用解碼和過濾技術(shù)。開發(fā)者可以使用簡(jiǎn)潔通用的接口來編寫一個(gè)簡(jiǎn)單的插件來添加新的解碼器或?yàn)V鏡。
1.2.5 JACK
Jack(JACK Audio Connection Kit 的遞歸縮寫)是一個(gè)專業(yè)級(jí)的聲音服務(wù)(守護(hù)進(jìn)程),它為聲音和MIDI數(shù)據(jù)提供實(shí)時(shí)的、低延時(shí)的連接,有關(guān)的程序使用JACK的API。
JACK能使用ALSA、PortAudio、CoreAudio、FFADO和OSS作為硬件層的后端。此外, 還有一個(gè)虛擬的驅(qū)動(dòng)(當(dāng)不需要聲音輸出時(shí)是很有用的,例如離線渲染)和一個(gè)通過UDP協(xié)議的音頻驅(qū)動(dòng)(Audio-over-UDP driver)。它可以運(yùn)行在Linux、Mac OS X、Solaris、Windows、FreeBSD、OpenBSD和NetBSD上。JACK的API被標(biāo)準(zhǔn)化,并且存在兩種可融合的實(shí)現(xiàn):jack1,由簡(jiǎn)單的C實(shí)現(xiàn)并且已經(jīng)維護(hù)了一段時(shí)間;至于jack2(原來的jackdmp),由Stéphane Letz領(lǐng)導(dǎo)的用C++重寫的實(shí)現(xiàn),jack2在積極開發(fā)中,目標(biāo)是支持多處理器和對(duì)其它非Linux操作系統(tǒng)。
1.2.6 Xin
如果說linux音頻發(fā)展像地球史,那xine就處在白堊紀(jì)。它就像個(gè)遺老,你仍能從很多播放器中發(fā)現(xiàn)它的身影,所以很多l(xiāng)inux發(fā)行版仍然捆綁 著xine。xine創(chuàng)立之初,設(shè)計(jì)分為前端和后端,前端用于和用戶交互,后端處理多媒體。得益于封裝的解碼庫(kù),它可以播放包括AVI、Matroska和 Ogg以及它們 包含的數(shù)十種格式,例如AAC、Flack、MP3、Vorbis和WMA。因?yàn)樗蕾囉趲?kù)實(shí)現(xiàn),所以xine被開發(fā)成一個(gè)多媒體框架,庫(kù)的開發(fā),使得xine在法律允許范圍內(nèi)對(duì)多媒體文件提供最好的支持。xine可以和 alsa,pulse通信,很多程序也可以調(diào)用xine,例如totme-xine。同時(shí)xine也是kde的Phonon默認(rèn)后端,所以不論是 Amarok 還是 Kaffeine,都能看到他的蹤跡。
1.2.7 Phonon
Phonon是KDE 4的多媒體API 。Phonon提供一個(gè)穩(wěn)定的API允許KDE 4獨(dú)立于任何一個(gè)聲音系統(tǒng)服務(wù)器如xine。Phonon讓各種后端提供界面給開發(fā)者所謂的”引擎”;每個(gè)引擎運(yùn)作在一個(gè)具體的后端。每個(gè)后端都可讓Phonon控制基本功能,如播放、暫停和搜尋。Phonon也支持更高層次的功能,如讓音軌轉(zhuǎn)化之間變微弱。使用Solid,Phonon將給予用戶更多配件的控制能力如耳機(jī)、揚(yáng)聲器、麥克風(fēng)。一個(gè)例子是,因?yàn)槟憧赡苤挥幸粋€(gè)VoIP會(huì)話使用您的耳機(jī),但所有其他的聲音通過揚(yáng)聲器出來。支援 Unix-like 系統(tǒng)下的后端xine、VLC、MPlayer。支援 Windows 下的后端 DirectShow、VLC和MPlayer.支持 Mac OS X下的后端QuickTime。QT4.4和之后版本使用了Phonon,作為跨平臺(tái)的音頻/視頻播放。
1.2.8、其他
其他有一些很多小眾的音頻技術(shù),例如ESD、SDL和 PortAudio。
ESD
ESD是聲音啟發(fā)守護(hù)進(jìn)程(Enlightenment Sound Daemon),它在曾經(jīng)很長(zhǎng)的一段時(shí)間里曾是Gnome桌面的默認(rèn)聲音服務(wù)。后來,Gnome開始使用libcanberra(它本身可以和ALSA、 GStreamer、OSS和PulseAudio通信),ESD在2009年4月被徹底放棄支持。在kde上esd也是杯具。因?yàn)榇蟛糠秩硕际鞘褂?kde4,所以phonon替代了esd。
SDL
SDL依然欣欣向榮的發(fā)展著。因?yàn)橐呀?jīng)是用他開發(fā)了上百款跨平臺(tái)游戲, 所以SDL庫(kù)的音頻輸出組件依然支持良好,具有大量新的特性,并且成熟而穩(wěn)定。
PortAudio
PortAudio也是一個(gè)跨平臺(tái)音頻庫(kù),它把 SGI、Unix和Beos加入到可能的終端混音器中。使用PortAudio的最知名的應(yīng)用程序就是Audacity音頻編輯器了,因?yàn)槭褂昧?portaudio,使得它音頻輸出遇到了問題,jack支持也遇到了bug。
二、ALSA框架分析
2.1 ALSA框架介紹
2.1.1 ALSA簡(jiǎn)介
ALSA 是 Advanced Linux Sound Architecture 的縮寫,即高級(jí) Linux聲音架構(gòu),在 Linux 操作系統(tǒng)上提供了對(duì)音頻和 MIDI(Musical InstrumentDigital Interface,音樂設(shè)備數(shù)字化接口)的支持。在 Linux2.6 版本內(nèi)核以后,ALSA 已經(jīng)成為默認(rèn)的聲音子系統(tǒng),用來替換 2.4 版本內(nèi)核中的OSS(Open Sound System,開放聲音系統(tǒng))。
ALSA 是一個(gè)完全開放源碼的音頻驅(qū)動(dòng)程序集,是由志愿者維護(hù)的開源項(xiàng)目,而OSS則是由公司提供的商業(yè)產(chǎn)品。ALSA系統(tǒng)包括驅(qū)動(dòng)包alsa-driver(集成在內(nèi)核源碼),開發(fā)包 alsa-libs,開發(fā)包插件 alsalibplugins,設(shè)置管理工具包 alsa-utils,其他聲音相關(guān)處理小程序包alsa-tools,特殊音頻固件支持包 alsa-firmware,OSS 接口兼容模擬層工具 alsa-oss 共 7 個(gè)子項(xiàng)目,其中只有 alsa-driver 是必須的。除了 alsa-driver,ALSA 包含在用戶空間的 alsa-lib 函數(shù)庫(kù),具有更加友好的編程接口,并且完全兼容于 OSS,開發(fā)者可以通過這些高級(jí) API 使用驅(qū)動(dòng),不必直接與內(nèi)核驅(qū)動(dòng) API 進(jìn)行交互。
ALSA 主要有如下特點(diǎn):
支持多種聲卡設(shè)備;
模塊化的內(nèi)核驅(qū)動(dòng)程序;
支持 SMP(對(duì)稱多處理)和多線程;
提供應(yīng)用開發(fā)函數(shù)庫(kù) ;
兼容 OSS 應(yīng)用程序 。
2.1.2 ALSA整體框架
ALSA 在 Linux 系統(tǒng)中可以主要分兩部分,在Kernel空間的設(shè)備驅(qū)動(dòng)層,ALSA 提供了 ALSA-driver,它是整個(gè) ALSA 框架的核心部分;同時(shí)在Linux User空間,ALSA 提供了alsa-lib,對(duì) ALSA-driver的系統(tǒng)調(diào)用API進(jìn)行封裝,應(yīng)用程序只要調(diào)用 alsa-lib 提供的 API,即可以完成對(duì)底層音頻硬件的控制。下圖2.1.2是基于ALSA框架的Linux音頻系統(tǒng)架構(gòu)圖:
圖2.1.2
2.1.2.1 alsa-lib
User空間的 alsa-lib 對(duì)應(yīng)用程序提供統(tǒng)一的 alsa-lib-API 接口,簡(jiǎn)化了應(yīng)用程序的實(shí)現(xiàn)難度。alsa-lib 主要以 plugin 插件的形式體現(xiàn)。詳細(xì)信息詳見http://www.alsa-project.org/alsa-doc/alsa-lib/ 。
2.1.2.2 ALSA-driver
Linux 內(nèi)核空間中,ALSA-driver 其大致可分為三層:聲卡對(duì)象描述層、ALSA 核心層 ASLA Core 和 Audio 設(shè)備驅(qū)動(dòng)層 Audio device driver。
最上層的是聲卡對(duì)象描述層,是聲卡硬件的抽象描述,是一個(gè)虛擬層,用戶空間通過這些描述可以得知該聲卡硬件的功能、設(shè)備組件和操作方法等。
中間層是 ASLA Croe,是 ALSA 的標(biāo)準(zhǔn)框架,是 ALSA-driver 的核心部分,提供了各種音頻設(shè)備驅(qū)動(dòng)的通用方法和數(shù)據(jù)結(jié)構(gòu),為 Audio driver提供 ALSA Driver API。
最底層是 Audio device driver,根據(jù) ALSA-driver 提供的 ALSA Driver API 和相應(yīng)音頻設(shè)備的初始化及工作流程,實(shí)現(xiàn)具體的功能組件函數(shù),這也是驅(qū)動(dòng)開發(fā)人員需要具體實(shí)現(xiàn)的部分。
2.2 ALSA的硬件抽象
ALSA 用 cards,device 和 subdevices 的分層結(jié)構(gòu)表示 Audio 硬件設(shè)備和他們的組件。這個(gè)分層結(jié)構(gòu)是 ALSA 看待硬件設(shè)備結(jié)構(gòu)和能力的視角,是對(duì)實(shí)體硬件的抽象化實(shí)例。見圖2.2:
圖2.2 ALSA設(shè)備抽象圖
目前 ALSA 內(nèi)核提供給用戶空間的 device 文件接口有:
InformationInterface(/proc/asound)信息接口; ControlInterface(/dev/snd/controlCX)控制接口; MixerInterface(/dev/snd/mixerCXDX)混音器接口; PCMInterface(/dev/snd/pcmCXDX) PCM 接口; RawMIDIInterface(/dev/snd/midiCXDX) Raw 迷笛接口; SequencerInterface(/dev/snd/seq)音序器接口; TimerInterface(/dev/snd/timer)定時(shí)器接口;
2.2.1 PCM設(shè)備
ALSA 已經(jīng)為我們實(shí)現(xiàn)了功能強(qiáng)勁的 PCM 中間層,自己的驅(qū)動(dòng)中只要實(shí)現(xiàn)一些底層的需要訪問硬件的函數(shù)即可。要訪問 PCM 的中間層代碼,你首先要包含頭文件
圖2.2.1 聲卡中的pcm結(jié)構(gòu)圖
2.2.2 Control設(shè)備
Control 接口主要讓用戶空間的應(yīng)用程序(alsa-lib)可以訪問和控制音頻 codec 芯片中的多路開關(guān),滑動(dòng)控件等。用戶空間通過對(duì) Control設(shè)備的操作,從而達(dá)到操作 CODEC 相關(guān)寄存器的目的。
2.2.3 ALSA設(shè)備文件命名規(guī)則
ALSA cards和聲卡硬件是一一對(duì)應(yīng)的,ALSA cards主要保存每塊卡上的設(shè)備列表,一個(gè)card可以通過一個(gè)ID(字符串)或者從0開始的數(shù)字表示。大部分 ALSA 硬件訪問發(fā)生在 device 級(jí)別,可以從 0 開始枚舉每個(gè)卡的 devices,不同的 devices 可以獨(dú)立的打開和使用。
典型的,聲卡和設(shè)備這兩個(gè)標(biāo)識(shí)足以決定聲音信號(hào)從哪里讀取,送到哪里。Subdevices 是 ALSA 能夠區(qū)分的更細(xì)粒度的對(duì)象。最常見的場(chǎng)景是一個(gè) device 的每個(gè) channel 都對(duì)應(yīng)一個(gè) subdevice 或者總共只有一個(gè)subdevice。一個(gè) device 的 subdevice 理論上可以單獨(dú)使用,但是在一個(gè)subdevice 上播放 multi-channel 信號(hào)時(shí),也會(huì)使用其余的 subdevices。和 device 一樣,subdevices 索引標(biāo)識(shí)從 0 開始。
2.2.4 ALSA 設(shè)備文件實(shí)例說明
下面舉例查看某 Linux 系統(tǒng)中 dev/snd 路徑下 alsa 驅(qū)動(dòng)設(shè)備文件:
crw-rw—-+ 1 root audio 116, 2 4 月 7 18:14 controlC0 crw-rw—-+ 1 root audio 116, 5 4月 7 18:14 controlC1 crw-rw—-+ 1 root audio 116, 3 4 月 7 18:15 pcmC0D3p crw-rw—-+ 1 root audio 116, 7 4 月 7 18:15 pcmC1D0c crw-rw—-+ 1 root audio 116, 6 4 月 18 10:38 pcmC1D0p crw-rw—-+ 1 root audio 116, 8 4 月 7 18:14 pcmC1D2c crw-rw—-+ 1 root audio 116, 1 4 月 7 18:14 seq crw-rw—-+ 1 root audio 116, 33 4 月 7 18:14 timer
我們可以看到以下設(shè)備文件:
controlCX –> 用于聲卡的控制,例如通道選擇,混音,麥克風(fēng)的控制等 pcmCXDXc –> 用于錄音的 pcm 設(shè)備 pcmCXDXp –> 用于播放的 pcm 設(shè)備 seq–>音序器 timer–>定時(shí)器
其中,CXDX 代表的是聲卡 X 中的設(shè)備 X,pcmC1D0c 最后一個(gè) c 代表 capture,pcmC1D0p 最后一個(gè) p 代表 playback,這些都是 alsa-driver中的命名規(guī)則。從上面的列表可以看出,聲卡下掛了 8 個(gè)設(shè)備,根據(jù)聲卡的實(shí)際能力,驅(qū)動(dòng)實(shí)際上可以掛上更多種類的設(shè)備。通常最重要的兩個(gè)設(shè)備是 PCM 和 control。
2.3 HDA Driver分析
2.3.1 HDA硬件系統(tǒng)框架
HDA(High Definition Audio)是intel設(shè)計(jì)的用來取代AC97的音頻標(biāo)準(zhǔn),硬件架構(gòu)上由hda dodec和hda controller組成見圖2.3.1:
圖2.3.1
2.3.2 Stream的概念
HAD 引入了 Streams 的概念來組織數(shù)據(jù),并通過 HDA Link 總線進(jìn)行數(shù)據(jù)傳輸。Stream 是一個(gè)在系統(tǒng)內(nèi)存緩沖區(qū)和 codec 之間創(chuàng)建的邏輯的或虛擬的連接用以來呈現(xiàn)數(shù)據(jù),該連接由單個(gè) DMA 通道通過 Link總線驅(qū)動(dòng)。一個(gè) Stream 包含一個(gè)或多個(gè)相關(guān)的組件或數(shù)據(jù) channels,每個(gè) channel 都被動(dòng)態(tài)綁定到 codec 中的一個(gè)單一 converter 上來呈現(xiàn)。
例如,一個(gè)立體聲 Stream 包括兩個(gè) channels:左和右,在此 Stream 中的每一個(gè)采樣點(diǎn)應(yīng)該包括兩個(gè)采樣數(shù)據(jù):左和右。這些采樣在緩沖區(qū)中和在鏈路上傳輸?shù)臅r(shí)候是組合在一起的,但是卻在 codec 中連接不同的DA 轉(zhuǎn)換器。
2.3.3 HDA driver模型介紹
2.3.3.1 重要結(jié)構(gòu)體azx
azx 是hda controller的結(jié)構(gòu)體,其中struct hda_bus bus、struct snd_card *card、struct pci_dev *pci是三個(gè)重要結(jié)構(gòu)體,分別表示總線、卡、設(shè)備。其kernel4.6版的結(jié)構(gòu)體見下:
struct azx { struct hda_bus bus; struct snd_card *card; struct pci_dev *pci; int dev_index; /* chip type specific */ int driver_type; unsigned int driver_caps; int playback_streams; int playback_index_offset; int capture_streams; int capture_index_offset; int num_streams; const int *jackpoll_ms; /* per-card jack poll interval */ /* Register interaction. */ const struct hda_controller_ops *ops; /* position adjustment callbacks */ azx_get_pos_callback_t get_position[2]; azx_get_delay_callback_t get_delay[2]; /* locks */ struct mutex open_mutex; /* Prevents concurrent open/close operations */ /* PCM */ struct list_head pcm_list; /* azx_pcm list */ /* HD codec */ int codec_probe_mask; /* copied from probe_mask option */ unsigned int beep_mode; #ifdef CONFIG_SND_HDA_PATCH_LOADER const struct firmware *fw; #endif /* flags */ int bdl_pos_adj; int poll_count; unsigned int running:1; unsigned int single_cmd:1; unsigned int polling_mode:1; unsigned int msi:1; unsigned int probing:1; /* codec probing phase */ unsigned int snoop:1; unsigned int align_buffer_size:1; unsigned int region_requested:1; unsigned int disabled:1; /* disabled by vga_switcheroo */ #ifdef CONFIG_SND_HDA_DSP_LOADER struct azx_dev saved_azx_dev; #endif };
2.3.3.2 hda dirver需要實(shí)現(xiàn)的操作功能函數(shù)
操作函數(shù)主要有兩類,一個(gè)是IO級(jí)操作函數(shù),即寄存器讀寫;一個(gè)是功能級(jí)操作函數(shù);
IO級(jí)操作:
structhdac_io_ops{ /*mappedregisteraccesses*/ void(*reg_writel)(u32value,u32__iomem*addr); u32(*reg_readl)(u32__iomem*addr); void(*reg_writew)(u16value,u16__iomem*addr); u16(*reg_readw)(u16__iomem*addr); void(*reg_writeb)(u8value,u8__iomem*addr); u8(*reg_readb)(u8__iomem*addr); /*Allocationops*/ int(*dma_alloc_pages)(structhdac_bus*bus,inttype,size_tsize,structsnd_dma_buffer*buf); void(*dma_free_pages)(structhdac_bus*bus,structsnd_dma_buffer*buf);};
功能級(jí)操作:
struct hda_controller_ops { /* Disable msi if supported, PCI only */ int (*disable_msi_reset_irq)(struct azx *); int (*substream_alloc_pages)(struct azx *chip, structsnd_pcm_substream*substream, size_t size); int (*substream_free_pages)(struct azx *chip, struct snd_pcm_substream *substream); void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream, struct vm_area_struct *area); /* Check if current position is acceptable */ int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); /* enable/disable the link power */ int (*link_power)(struct azx *chip, bool enable); };
2.3.3.3 HDA dirver初始化流程
hda dirver的初始化流程見圖2.3.3.3:
圖2.3.3.3
三、ALSA-lib嵌入式平臺(tái)移植
雖然linux下alsa框架給用戶空間提供了系統(tǒng)調(diào)用,但alsa-lib對(duì)系統(tǒng)調(diào)用進(jìn)行進(jìn)一步封裝,并實(shí)現(xiàn)了很多插件,例如多音頻源進(jìn)行混音播放時(shí),調(diào)用的就是 dmix 插件。
3.1 軟件包下載
進(jìn)入網(wǎng)站選擇下載合適版本的軟件包,見圖3.1:
圖3.1
其中,alsa-lib是ALSA 應(yīng)用庫(kù)(必需基礎(chǔ)庫(kù)),alsa-utils包含一些ALSA小的測(cè)試工具.如aplay、arecord 、amixer播放、錄音和調(diào)節(jié)音量小程序,對(duì)于一些應(yīng)用開發(fā)者只需要以上兩個(gè)軟件包就可以了。
3.2 配置和編譯
3.2.1 alsa-lib
準(zhǔn)備
解壓alsa-lib-x.x.x.tar.bz2,進(jìn)入解壓后目錄:
cd alsa-lib-x.x.x
配置
./configure --host=aarch64-linux-gnu --prefix=/usr/local/share/arm64-alsa --enable-static=yes --enable-shared=no --enable-python=no --with-configdir=/usr/local/share/alsa --with-plugindir=/usr/local/lib/alsa_lib --with-pcm-plugins=hw
其中配置參數(shù)–prefix=/usr/local/share/arm64-alsa 是編譯后結(jié)果的輸出路徑,–with-configdir=/usr/local/share/alsa它將影響 include/config.h中的 ALSA_CONFIG_DIR 目錄。
編譯
make
安裝
make install
3.2.2 alsa-utils
準(zhǔn)備
解壓alsa-utils-x.x.x.tar.bz2,進(jìn)入解壓后目錄:
cd alsa-utils-x.x.x
配置
./configure --host=aarch64-linux-gnu --prefix=/usr/local/share/arm64-alsa CFLAGS="-I/usr/local/share/arm64-alsa/include" LDFLAGS="-L/usr/local/share/arm64-alsa/lib --lasound" --disable-alsamixer --disable-xmlto
編譯
make
安裝
make install
3.2.3 移植
準(zhǔn)備:
復(fù)制目標(biāo)文件夾下的文件到嵌入式系統(tǒng)的根文件系統(tǒng):
cp -rfa /usr/local/share/arm64-alsa/lib/* /initramfs/lib/ cp -rfa /usr/local/share/arm64-alsa/bin/* /initramfs/sbin/ cp -rfa /usr/local/share/arm64-alsa/sbin/* /initramfs/sbin/ cp -rfa /usr/local/share/alsa/* /initramfs/usr/local/share/
配置環(huán)境變量:
在rootfs/etc/profile,添加如下兩行:
alsa_init export ALSA_CONFIG_PATH=/usr/local/share/alsa/alsa.conf
生成跟文件系統(tǒng):
find .|cpio -o -H newc|gzip -9 > $(pwd)/initramfs.img.gz
3.3 相關(guān)軟件應(yīng)用
在alsa-utils包含一些ALSA小的測(cè)試工具,這些工具軟件都是基于alsa-lib的API實(shí)現(xiàn)的,其中amixer可以進(jìn)行音頻通道選通和音量調(diào)節(jié),aplay是播放音頻軟件,arecord是錄音軟件。
審核編輯:劉清
-
PCM
+關(guān)注
關(guān)注
1文章
195瀏覽量
53230 -
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
593瀏覽量
27397 -
電平信號(hào)
+關(guān)注
關(guān)注
3文章
24瀏覽量
9142 -
alsa
+關(guān)注
關(guān)注
0文章
19瀏覽量
3618
原文標(biāo)題:ALSA(高級(jí)Linux聲音架構(gòu))淺析
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論