Linux音频驱动简述
一、數(shù)字音頻
音頻信號是一種連續(xù)變化的模擬信號,但計算機僅僅能處理和記錄二進制的數(shù)字信號。由自然音源得到的音頻信號必須經(jīng)過一定的變換,成為數(shù)字音頻信號之后,才干送到計算機中作進一步的處理。
數(shù)字音頻系統(tǒng)通過將聲波的波型轉(zhuǎn)換成一系列二進制數(shù)據(jù),來實現(xiàn)對原始聲音的重現(xiàn),實現(xiàn)這一步驟的設(shè)備常被稱為模/數(shù)轉(zhuǎn)換器(A/D)。A/D轉(zhuǎn)換器以每秒鐘上萬次的速率對聲波進行採樣,每個採樣點都記錄下了原始模擬聲波在某一時刻的狀態(tài),通常稱之為樣本(sample),而每一秒鐘所採樣的數(shù)目則稱為採樣頻率,通過將一串連續(xù)的樣本連接起來。就能夠在計算機中描寫敘述一段聲音了。對于採樣過程中的每個樣本來說,數(shù)字音頻系統(tǒng)會分配一定存儲位來記錄聲波的振幅,一般稱之為採樣分辨率或者採樣精度,採樣精度越高,聲音還原時就會越細膩。
數(shù)字音頻涉及到的概念許多,對于在Linux下進行音頻編程的程序猿來說。最重要的是理解聲音數(shù)字化的兩個關(guān)鍵步驟:採樣和量化。
採樣就是每隔一定時間就讀一次聲音信號的幅度。而量化則是將採樣得到的聲音信號幅度轉(zhuǎn)換為數(shù)字值,從本質(zhì)上講,採樣是時間上的數(shù)字化,而量化則是幅度上的數(shù)字化。
以下介紹幾個在進行音頻編程時常常須要用到的技術(shù)指標:
採樣頻率
採樣頻率是指將模擬聲音波形進行數(shù)字化時,每秒鐘抽取聲波幅度樣本的次數(shù)。採樣頻率的選擇應(yīng)該遵循奈奎斯特(Harry Nyquist)採樣理論:假設(shè)對某一模擬信號進行採樣,則採樣后可還原的最高信號頻率僅僅有採樣頻率的一半,或者說僅僅要採樣頻率高于輸入信號最高頻率的兩倍,就能從採樣信號系列重構(gòu)原始信號。
正常人聽覺的頻率范圍大約在20Hz~20kHz之間,依據(jù)奈奎斯特採樣理論,為了保證聲音不失真,採樣頻率應(yīng)該在40kHz左右。經(jīng)常使用的音頻採樣頻率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,假設(shè)採用更高的採樣頻率,還能夠達到DVD的音質(zhì)。
量化位數(shù)
量化位數(shù)是對模擬音頻信號的幅度進行數(shù)字化。它決定了模擬信號數(shù)字化以后的動態(tài)范圍,經(jīng)常使用的有8位、12位和16位。
量化位越高,信號的動態(tài)范圍越大,數(shù)字化后的音頻信號就越可能接近原始信號,但所須要的存貯空間也越大。
聲道數(shù)
聲道數(shù)是反映音頻數(shù)字化質(zhì)量的還有一個重要因素,它有單聲道和雙聲道之分。
雙聲道又稱為立體聲,在硬件中有兩條線路,音質(zhì)和音色都要優(yōu)于單聲道,但數(shù)字化后占領(lǐng)的存儲空間的大小要比單聲道多一倍。
二、聲卡驅(qū)動
出于對安全性方面的考慮,Linux下的應(yīng)用程序無法直接對聲卡這類硬件設(shè)備進行操作,而是必須通過內(nèi)核提供的驅(qū)動程序才干完畢。在Linux上進行音頻編程的本質(zhì)就是要借助于驅(qū)動程序,來完畢對聲卡的各種操作。對硬件的控制涉及到寄存器中各個比特位的操作,通常這是與設(shè)備直接相關(guān)而且對時序的要求很嚴格,假設(shè)這些工作都交由應(yīng)用程序猿來負責。那么對聲卡的編程將變得異常復雜而困難起來,驅(qū)動程序的作用正是要屏蔽硬件的這些底層細節(jié),從而簡化應(yīng)用程序的編寫。
眼下Linux下經(jīng)常使用的聲卡驅(qū)動程序主要有兩種:OSS和ALSA。
ALSA和OSS最大的不同之處在于ALSA是由志愿者維護的自由項目,而OSS則是由公司提供的商業(yè)產(chǎn)品,因此在對硬件的適應(yīng)程度上OSS要優(yōu)于ALSA,它可以支持的聲卡種類很多其它。
ALSA盡管不及OSS運用得廣泛。但卻具有更加友好的編程接口,而且全然兼容于OSS,相應(yīng)用程序猿來講無疑是一個更佳的選擇。
三、Linux OSS音頻設(shè)備驅(qū)動
3.1 OSS驅(qū)動的組成
OSS標準中有2個最主要的音頻設(shè)備:mixer(混音器)和DSP(數(shù)字信號處理器)。
在聲卡的硬件電路中,mixer是一個非常重要的組成部分,它的作用是將多個信號組合或者疊加在一起,對于不同的聲卡來說,其混音器的作用可能各不同樣。
OSS驅(qū)動中。/dev/mixer設(shè)備文件是應(yīng)用程序?qū)ixer進行操作的軟件接口。
混音器電路通常由兩個部分組成:輸入混音器(input mixer)和輸出混音器(output mixer)。
輸入混音器負責從多個不同的信號源接收模擬信號,這些信號源有時也被稱為混音通道或者混音設(shè)備。模擬信號通過增益控制器和由軟件控制的音量調(diào)節(jié)器后,在不同的混音通道中進行級別(level)調(diào)制。然后被送到輸入混音器中進行聲音的合成。混音器上的電子開關(guān)能夠控制哪些通道中有信號與混音器相連。有些聲卡僅僅同意連接一個混音通道作為錄音的音源,而有些聲卡則同意對混音通道做隨意的連接。經(jīng)過輸入混音器處理后的信號仍然為模擬信號。它們將被送到A/D轉(zhuǎn)換器進行數(shù)字化處理。
輸出混音器的工作原理與輸入混音器類似,相同也有多個信號源與混音器相連。并且事先都經(jīng)過了增益調(diào)節(jié)。當輸出混音器對全部的模擬信號進行了混合之后,通常還會有一個總控增益調(diào)節(jié)器來控制輸出聲音的大小,此外另一些音調(diào)控制器來調(diào)節(jié)輸出聲音的音調(diào)。經(jīng)過輸出混音器處理后的信號也是模擬信號,它們終于會被送給喇叭或者其他的模擬輸出設(shè)備。
對混音器的編程包含如何設(shè)置增益控制器的級別。以及如何在不同的音源間進行切換。這些操作通常來講是不連續(xù)的,并且不會像錄音或者放音那樣須要占用大量的計算機資源。
因為混音器的操作不符合典型的讀/寫操作模式,因此除了
open()和close()兩個系統(tǒng)調(diào)用之外,大部分的操作都是通過ioctl()系統(tǒng)調(diào)用來完畢的。與/dev/dsp不同,/dev/mixer同意多個應(yīng)用程序同一時候訪問。而且混音器的設(shè)置值會一直保持到相應(yīng)的設(shè)備文件被關(guān)閉為止。
DSP也稱為編解碼器,實現(xiàn)錄音(錄音)和放音(播放)。其相應(yīng)的設(shè)備文件是/dev/dsp或/dev/sound/dsp。OSS聲卡驅(qū)動程序提供的 /dev/dsp是用于數(shù)字採樣和數(shù)字錄音的設(shè)備文件。向該設(shè)備寫數(shù)據(jù)即意味著激活聲卡上的D/A轉(zhuǎn)換器進行放音,而向該設(shè)備讀數(shù)據(jù)則意味著激活聲卡上的
A/D轉(zhuǎn)換器進行錄音。
在從DSP設(shè)備讀取數(shù)據(jù)時,從聲卡輸入的模擬信號經(jīng)過A/D轉(zhuǎn)換器變成數(shù)字採樣后的樣本,保存在聲卡驅(qū)動程序的內(nèi)核緩沖區(qū)中,當應(yīng)用程序通過 read()系統(tǒng)調(diào)用從聲卡讀取數(shù)據(jù)時,保存在內(nèi)核緩沖區(qū)中的數(shù)字採樣結(jié)果將被拷貝到應(yīng)用程序所指定的用戶緩沖區(qū)中。須要指出的是。聲卡採樣頻率是由內(nèi)核中的驅(qū)動程序所決定的,而不取決于應(yīng)用程序從聲卡讀取數(shù)據(jù)的速度。假設(shè)應(yīng)用程序讀取數(shù)據(jù)的速度過慢,以致低于聲卡的採樣頻率,那么多余的數(shù)據(jù)將會被丟棄(即overflow)。假設(shè)讀取數(shù)據(jù)的速度過快,以致高于聲卡的採樣頻率。那么聲卡驅(qū)動程序?qū)氯切┱埱髷?shù)據(jù)的應(yīng)用程序。直到新的數(shù)據(jù)到來為止。
在向DSP設(shè)備寫入數(shù)據(jù)時。數(shù)字信號會經(jīng)過D/A轉(zhuǎn)換器變成模擬信號。然后產(chǎn)生出聲音。應(yīng)用程序?qū)懭霐?shù)據(jù)的速度應(yīng)該至少等于聲卡的採樣頻率,過慢會產(chǎn)生聲音暫停或者停頓的現(xiàn)象(即underflow)。假設(shè)用戶寫入過快的話,它會被內(nèi)核中的聲卡驅(qū)動程序堵塞,直到硬件有能力處理新的數(shù)據(jù)為止。
與其他設(shè)備有所不同,聲卡通常不須要支持非堵塞(non-blocking)的I/O操作。
即便內(nèi)核OSS驅(qū)動提供了非堵塞的I/O支持,用戶空間也不宜採用。
不管是從聲卡讀取數(shù)據(jù),或是向聲卡寫入數(shù)據(jù),其實都具有特定的格式(format)。如無符號8位、單聲道、8KHz採樣率,假設(shè)默認值無法達到要求,能夠通過ioctl()系統(tǒng)調(diào)用來改變它們。通常說來,在應(yīng)用程序中打開設(shè)備文件/dev/dsp之后。接下去就應(yīng)該為其設(shè)置恰當?shù)?#26684;式。然后才干從聲卡讀取或者寫入數(shù)據(jù)。
3.2 mixer接口
int register_sound_mixer(structfile_operations *fops, int dev);
上述函數(shù)用于注冊1個混音器,第1個參數(shù)fops即是文件操作接口,第2個參數(shù)dev是設(shè)備編號,假設(shè)填入-1,則系統(tǒng)自己主動分配1個設(shè)備編號。
mixer 是 1個典型的字符設(shè)備,因此編碼的主要工作是實現(xiàn)file_operations中的open()、ioctl()等函數(shù)。
mixer接口file_operations中的最重要函數(shù)是ioctl()。它實現(xiàn)混音器的不同IO控制命令。
3.3 DSP接口
int register_sound_dsp(structfile_operations *fops, int dev);
上述函數(shù)與register_sound_mixer()類似,它用于注冊1個dsp設(shè)備,第1個參數(shù)fops即是文件操作接口,第2個參數(shù)dev是設(shè)備編號,假設(shè)填入-1。則系統(tǒng)自己主動分配1個設(shè)備編號。
dsp也是1個典型的字符設(shè)備。因此編碼的主要工作是實現(xiàn)file_operations中的read()、write()、ioctl()等函數(shù)。
dsp接口file_operations中的read()和write()函數(shù)很重要。read()函數(shù)從音頻控制器中獲取錄音數(shù)據(jù)到緩沖區(qū)并復制到用戶空間,write()函數(shù)從用戶空間拷貝音頻數(shù)據(jù)到內(nèi)核空間緩沖區(qū)并終于發(fā)送到音頻控制器。
dsp接口file_operations中的ioctl()函數(shù)處理對採樣率、量化精度、DMA緩沖區(qū)塊大小等參數(shù)設(shè)置IO控制命令的處理。
在數(shù)據(jù)從緩沖區(qū)復制到音頻控制器的過程中,一般會使用DMA,DMA對聲卡而言很重要。比如,在放音時。驅(qū)動設(shè)置完DMA控制器的源數(shù)據(jù)地址(內(nèi)存中 DMA緩沖區(qū))、目的地址(音頻控制器FIFO)和DMA的數(shù)據(jù)長度,DMA控制器會自己主動發(fā)送緩沖區(qū)的數(shù)據(jù)填充FIFO。直到發(fā)送完對應(yīng)的數(shù)據(jù)長度后才中斷一次。
在OSS驅(qū)動中。建立存放音頻數(shù)據(jù)的環(huán)形緩沖區(qū)(ring buffer)一般是值得推薦的方法。
此外,在OSS驅(qū)動中,通常會將1個較大的DMA緩沖區(qū)分成若干個大小同樣的塊(這些塊也被稱為“段”,即
fragment),驅(qū)動程序使用DMA每次在聲音緩沖區(qū)和聲卡之間搬移一個fragment。在用戶空間。能夠使用ioctl()系統(tǒng)調(diào)用來調(diào)整塊的大小和個數(shù)。
除了read()、write()和ioctl()外,dsp接口的poll()函數(shù)通常也須要被實現(xiàn),以向用戶反饋眼下是否能讀寫DMA緩沖區(qū)。
在OSS驅(qū)動初始化過程中,會調(diào)用register_sound_dsp()和register_sound_mixer()注冊dsp和mixer設(shè)備。在模塊卸載的時候。會調(diào)用unregister_sound_dsp(audio_dev_dsp)和unregister_sound_mixer(audio_dev_mixer)。
Linux OSS驅(qū)動結(jié)構(gòu)例如以下圖所看到的:
3.4 OSS用戶空間編程
1、DSP編程
DSP接口的操作一般包含例如以下幾個步驟:
①
打開設(shè)備文件/dev/dsp
採用何種模式對聲卡進行操作也必須在打開設(shè)備時指定,對于不支持全雙工的聲卡來說,應(yīng)該使用僅僅讀或者僅僅寫的方式打開,僅僅有那些支持全雙工的聲卡,才干以讀寫的方式打開,這還依賴于驅(qū)動程序的詳細實現(xiàn)。Linux同意應(yīng)用程序多次打開或者關(guān)閉與聲卡相應(yīng)的設(shè)備文件,從而可以非常方便地在放音狀態(tài)和錄音狀態(tài)之間進行切換。
②
假設(shè)有須要,設(shè)置緩沖區(qū)大小
執(zhí)行在Linux內(nèi)核中的聲卡驅(qū)動程序?qū)iT維護了一個緩沖區(qū),其大小會影響到放音和錄音時的效果,使用ioctl()系統(tǒng)調(diào)用能夠?qū)λ某叽邕M行恰當?shù)脑O(shè)置。調(diào)節(jié)驅(qū)動程序中緩沖區(qū)大小的操作不是必須的,假設(shè)沒有特殊的要求,一般採用默認的緩沖區(qū)大小也就能夠了。
假設(shè)想設(shè)置緩沖區(qū)的大小。則通常應(yīng)緊跟在設(shè)備文件打開之后,這是由于對聲卡的其他操作有可能會導致驅(qū)動程序無法再改動其緩沖區(qū)的大小。
③
設(shè)置聲道(channel)數(shù)量
依據(jù)硬件設(shè)備和驅(qū)動程序的詳細情況。能夠設(shè)置為單聲道或者立體聲。
④
設(shè)置採樣格式和採樣頻率
採樣格式包含AFMT_U8(無符號8位)、AFMT_S8(有符號8位)、AFMT_U16_LE(小端模式,無符號16位)、 AFMT_U16_BE(大端模式,無符號16位)、AFMT_MPEG、AFMT_AC3等。使用SNDCTL_DSP_SETFMT IO控制命令能夠設(shè)置採樣格式。
對于大多數(shù)聲卡來說。其支持的採樣頻率范圍一般為5kHz到44.1kHz或者48kHz。但并不意味著該范圍內(nèi)的全部連續(xù)頻率都會被硬件支持,在 Linux下進行音頻編程時最經(jīng)常使用到的幾種採樣頻率是11025Hz、16000Hz、22050Hz、32000Hz 和44100Hz。使用SNDCTL_DSP_SPEED IO控制命令能夠設(shè)置採樣頻率。
⑤
讀寫/dev/dsp實現(xiàn)播放或錄音
2. mixer編程
聲卡上的混音器由多個混音通道組成,它們能夠通過驅(qū)動程序提供的設(shè)備文件/dev/mixer進行編程。
對聲卡的輸入增益和輸出增益進行調(diào)節(jié)是混音器的一個主要作用,眼下大部分聲卡採用的是8位或者16位的增益控制器,聲卡驅(qū)動程序會將它們轉(zhuǎn)換成百分比的形式。也就是說不管是輸入增益還是輸出增益。其取值范圍都是從0~100。
總結(jié)
以上是生活随笔為你收集整理的Linux音频驱动简述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PYTHON1.day21
- 下一篇: 安兔兔评测手机芯片性能评测怎么查 安兔兔