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