一、ALSA基礎知識
1. ALSA(Advanced Linux Sound Architecture)目前已經成為了linux的主流音頻體系結構,ALSA開源項目網址:http://www.alsa-project.org/。
另一個音頻驅動框架是OSS(open sound system),收費,已經廢棄。
2.在內核設備驅動層,ALSA提供了alsa-driver,同時在應用層,ALSA提供了alsa-lib,應用程序只要調用alsa-lib提供的API,即可以完成對底層音頻硬件的控制。
3.PCM(Pulse-code modulation)是脈沖編碼調制,PCM信號的兩個重要指標是采樣頻率和量化精度,目前,CD音頻的采樣頻率通常為44100Hz,量化精度是16bit。
播放音樂時,應用程序從存儲介質中讀取音頻數據(MP3、WMA、AAC...),經過解碼后,最終送到音頻驅動程序中的就是PCM數據;在錄音時,音頻驅動不停地把采樣所得的PCM數據送回給應用程序,由應用程序完成壓縮、存儲等任務。所以,音頻驅動的兩大核心任務就是:
playback:如何把用戶空間的應用程序發過來的PCM數據,轉化為人耳可以辨別的模擬音頻
capture:把mic拾取到得模擬信號,經過采樣、量化,轉換為PCM信號送回給用戶空間的應用程序
4.采集兩路數據稱為雙通道,wav格式的文件就是原始的采集聲音數據的文件,壓縮后可為mp3文件。
5.音頻驅動入口文件(注冊主設備號的文件)
alsa_sound_init //sound\core\sound.c
register_chrdev(116, "alsa", &snd_fops) //snd_fops中只有open()
音頻系統創建的所有設備文件都以struct snd_minor的形式存儲在全局數據snd_minors[]中,snd_fops.open()根據次設備號起中轉功能。
6.ALSA發展歷程:ALSA ---> ASoC --->DAPM,ASoC和DAPM將在后續博客講。
7.相關概念
HiFi:High-Fidelity的縮寫,翻譯為“高保真”,其定義是:與原來的聲音高度相似的重放聲音。
PCM: Pulse-code modulation,中文譯名是脈沖編碼調制。
DAI: Digital Audio Interface
MIDI:Music Instrument Digital Interface
二、Control設備的創建
1. Control接口主要讓用戶空間的應用程序(alsa-lib)可以訪問和控制音頻codec芯片中的多路開關,滑動控件等。對於Mixer(混音)來說,Control接口顯得尤為重要,從ALSA 0.9.x版本開始,所有的mixer工作都是通過control接口的API來實現的。使用snd_kcontrol_new結構來定義一個Control項,根據codec的芯片手冊進行構造snd_kcontrol_new。
2.設置cidec配置的統一的接口就是snd_kcontrol,一個snd_kcontrol表示一個功能(可能是一個寄存器的某些位),每個sndkcontrol中有自己的讀寫函數。一個聲卡有多個kcontrol,一個kcontrol對應一個功能,比如:音量,開關錄音。kcontrol中有函數來設置功能。snd_kcontrol對應的是功能,其寄存器配置由codec驅動負責。
3.kcontrol創建過程示例
struct snd_kcontrol_new wm8960_snd_controls[] //wm8960.c snd_soc_add_controls(codec, wm8960_snd_controls, ARRAY_SIZE(wm8960_snd_controls)); snd_ctl_add(card, snd_soc_cnew(control, codec, control->name, codec->name_prefix)); //將snd_kcontrol_new結構轉換成snd_kcontrol結構 snd_soc_cnew(control, codec, control->name, codec->name_prefix) //獲取一個snd_kcontrol結構 kcontrol = snd_ctl_new1(&template, data); //然后將這些snd_kcontrol結構串接在snd_card.controls域中。 list_add_tail(&kcontrol->list, &card->controls);
二、聲卡的創建
1. 使用struct snd_card表示,其是一個父設備,下面掛載着control pcm節點分別使用snd_device結構表示。snd_card可以說是整個ALSA音頻驅動最頂層的一個結構,整個聲卡的軟件邏輯結構開始於該結構,幾乎所有與聲音相關的邏輯設備都是在snd_card的管理之下,聲卡驅動的第一個動作通常就是創建一個snd_card結構體。
2. 聲卡的創建過程
snd_card_create // sound/core/init.c //創建聲卡的控制接口 snd_ctl_create(card); // sound/core/control.c //在聲卡注冊的時候會調用所有組件的dev_register回調來創建對應的設備節點: snd_card_register(struct snd_card *card);//sound/core/init.c snd_device_register_all(card) list_for_each_entry(dev, &card->devices, list) dev->ops->dev_register(dev) //注冊所有的屬於此Card的設備節點 //對應control節點 snd_device_ops.dev_register = snd_ctl_dev_register, snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, &snd_ctl_f_ops, /*name=*/"controlC0") //對應pcm節點 .dev_register = snd_pcm_dev_register, snd_register_device_for_dev(&snd_pcm_f_ops[0:p/1:c]);
聲卡設備/dev/snd/controlCX的file_operations是snd_ctl_f_ops //sound/core/control.c
聲卡設備/dev/snd/pcmCXDXp的file_operations是snd_pcm_f_ops[0], /dev/snd/pcmCXDXc的file_operations是snd_pcm_f_ops[1] //pcm_native.c
4. 一個pcm就是一個邏輯device,它里面有兩個通道,一個是playback通道,對應/dev/pcmC0D0p節點,另一個是capture通道,對應/dev/pcmC0D0c節點.
5. 創建聲卡的功能部件(邏輯設備),例如PCM,Mixer,MIDI等的函數如下
PCM —— snd_pcm_new() snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops) RAWMIDI —— snd_rawmidi_new() snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops) CONTROL —— snd_ctl_create() snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); TIMER —— snd_timer_new() snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); INFO —— snd_card_proc_new() snd_device_new(card, SNDRV_DEV_INFO, entry, &ops) JACK —— snd_jack_new() snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
參考:
Linux ALSA聲卡驅動之一:ALSA架構簡介:https://blog.csdn.net/DroidPhone/article/details/6271122
Linux ALSA聲卡驅動之二:聲卡的創建:https://blog.csdn.net/droidphone/article/details/6289712
Linux ALSA聲卡驅動之三:PCM設備的創建:https://blog.csdn.net/droidphone/article/details/6308006
Linux ALSA聲卡驅動之四:Control設備的創建 :https://blog.csdn.net/gjy938815/article/details/9209457