日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ALSA(一)

發(fā)布時(shí)間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ALSA(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://antkillerfarm.github.io/

參考文獻(xiàn)

ALSA(Advanced Linux Sound Architecture)是Linux內(nèi)核默認(rèn)的音頻驅(qū)動(dòng)框架。以下是一些參考資料:

http://www.alsa-project.org/main/index.php/Tutorials_and_Presentations

包含官方提供的若干教程。

http://blog.sina.com.cn/s/blog_5707eebf0100tjbe.html

這篇文章介紹了ALSA的代碼文件結(jié)構(gòu)。

http://blog.csdn.net/droidphone/article/details/6271122

系列文章共8篇,詳細(xì)介紹了ALSA和ASOC。該博客還有7篇與DAPM有關(guān)的博文。

http://blog.chinaunix.net/uid-20602659-id-2981336.html

系列文章共2篇。主要偏重于ASOC驅(qū)動(dòng)的具體實(shí)現(xiàn),而不是背后的機(jī)制原理。

關(guān)于ALSA的應(yīng)用層

查找PC本機(jī)驅(qū)動(dòng)

首先使用lspci -v列出所有的硬件設(shè)備,其中當(dāng)然也包括了音頻設(shè)備。例如我的PC上是這樣的:

Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 05)Subsystem: ASUSTeK Computer Inc. Device 1b73Flags: bus master, fast devsel, latency 0, IRQ 54Memory at df000000 (64-bit, non-prefetchable) [size=16K]Capabilities: <access denied>Kernel driver in use: snd_hda_intel

從驅(qū)動(dòng)名snd_hda_intel可以很輕松的發(fā)現(xiàn),這個(gè)驅(qū)動(dòng)的源代碼是sound/pci/hda/hda_intel.c。

在/dev/snd下,可以看到聲卡的子設(shè)備。

對(duì)于ASoC驅(qū)動(dòng)來(lái)說(shuō),因?yàn)樗莗latform驅(qū)動(dòng),所以可以在/sys/bus/platform下,找到驅(qū)動(dòng)的相關(guān)痕跡。

alsa-utils

alsa-utils是ALSA項(xiàng)目提供的工具軟件集,以下是一些測(cè)試樣例:

播放wave文件

aplay /mnt/nfs/test.wav

變頻播放(以44 KHz來(lái)播放音頻)

aplay -D rate_44k /mnt/nfs/test.wav

錄音,以20秒的間隔(-d 20),立體聲(-c 2),頻率是 8000Hz來(lái)錄制Wave格式音頻

arecord -d 20 -c 2 -t wav -r 8000 -f "Signed 16 bit Little Endian" /mnt/nfs/test.wav

測(cè)試混音播放(先是播放test1.wav,然后再同時(shí)播放test2.wav)

aplay -D plug:dmix_44k /mnt/nfs/test1.wav &
aplay -D plug:dmix_44k /mnt/nfs/test2.wav

設(shè)置放音增益(0 to 3)

amixer set Master 1

設(shè)置錄音音量(0-31)

amixer set Line 10

列出可用的ALSA設(shè)備

aplay -L

ALSA System on Chip (ASoC) layer

這是專(zhuān)為嵌入式設(shè)備設(shè)計(jì)的ALSA框架。官網(wǎng)是:

http://www.alsa-project.org/main/index.php/ASoC

上圖是TI某平臺(tái)的ASOC架構(gòu)圖。其中的ASoC layer可分為三個(gè)不同的部分:

1.Codec driver。這部分是平臺(tái)無(wú)關(guān)的,包括了音頻接口配置、音頻控制、電源管理和其他IO功能。所謂平臺(tái)是若干使用相同SOC的機(jī)型的集合。

2.Platform driver。這部分主要是平臺(tái)相關(guān)的音頻接口驅(qū)動(dòng)和相關(guān)的DMA驅(qū)動(dòng)。

3.Machine driver。這部分用于前兩部分之間的協(xié)調(diào),起到粘合劑的作用。它通常是與具體使用的機(jī)器相關(guān)的。

以三星設(shè)備為例,Platform driver和Machine driver在sound/soc/samsung下,該文件夾的Makefile節(jié)選如下:

# S3c24XX Platform Support snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o snd-soc-s3c2412-i2s-objs := s3c2412-i2s.oobj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o# S3C24XX Machine Support snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.oobj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o

Codec driver在sound/soc/codecs下,該文件夾的Makefile節(jié)選如下:

snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.oobj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o

snd_soc_register_codec函數(shù)用來(lái)注冊(cè)Codec driver。

snd_soc_register_component函數(shù)用來(lái)注冊(cè)外設(shè)接口驅(qū)動(dòng)(例如I2S)。

snd_soc_register_platform函數(shù)用來(lái)注冊(cè)Platform driver。

Machine driver通過(guò)snd_soc_dai_link結(jié)構(gòu)的codec_name和platform_name成員,指定匹配的Codec driver和Platform driver。

三部分的加載順序:

1.驅(qū)動(dòng)對(duì)象的加載,一般在模塊加載時(shí)進(jìn)行。各對(duì)象的先后順序無(wú)關(guān)緊要。

2.設(shè)備對(duì)象的加載,一般在驅(qū)動(dòng)對(duì)象加載之后,而在ALSA加載之前。由于模塊加載的初始化優(yōu)先級(jí)是device_initcall,而alsa_sound_last_init函數(shù)的初始化優(yōu)先級(jí)是late_initcall_sync,因此設(shè)備對(duì)象的初始化優(yōu)先級(jí)設(shè)為late_initcall是比較妥當(dāng)?shù)摹?/p>

3.由于Machine driver在Codec driver和Platform driver之間起著橋梁作用,因此需要在加載了Codec和Platform的設(shè)備對(duì)象之后,再進(jìn)行Machine設(shè)備對(duì)象的加載。

PCM, I2S, DMA

無(wú)論何種形式的音頻,最終都要轉(zhuǎn)換成PCM格式的數(shù)據(jù)(有時(shí)也被稱(chēng)作原始音頻數(shù)據(jù)),然后才能發(fā)送給相關(guān)的硬件。CPU和音頻芯片之間的數(shù)據(jù)接口,在PC上主要是AC97接口,而在嵌入式設(shè)備中,則多為I2S接口。

通常使用DMA方式傳輸原始音頻數(shù)據(jù)。在3.X內(nèi)核中,一般將PCM的DMA功能設(shè)置為Platform driver,而將I2S功能設(shè)置為該driver的一個(gè)component。

從DMA的實(shí)現(xiàn)方式來(lái)看,主要分兩種:

1.Platform driver包含i2s和pcm兩個(gè)文件。它的核心是設(shè)置snd_pcm_ops數(shù)據(jù)結(jié)構(gòu)。例如pxa2xx-i2s.c和pxa2xx-pcm.c。

2.Platform driver只包含i2s一個(gè)文件。它主要調(diào)用與dmaengine_pcm_platform結(jié)構(gòu)相關(guān)的函數(shù)。例如s3c24xx-i2s.c。

ASoC術(shù)語(yǔ)表

DAI: Digital Audio Interface

DAPM:Dynamic Audio Power Management

ALSA從2.6.X到3.X的變化細(xì)節(jié)

網(wǎng)上的文章有不少都是針對(duì)2.6.X的老內(nèi)核的,現(xiàn)將3.X引入的變化,羅列如下:(自己摘錄,僅供備忘,非官方內(nèi)容)

1.snd_card_create改為snd_card_new。

從Gstreamer到ALSA

0.概述

Gstreamer通過(guò)alsasink和alsasrc這兩個(gè)插件訪問(wèn)ALSA API。這兩個(gè)插件在gst-plugins-base代碼的ext/alsa文件夾下。

gst-plugins-base的git地址是:

git://anongit.freedesktop.org/gstreamer/gst-plugins-base

ALSA API的代碼在alsa-lib中,它的git地址是:

git://git.alsa-project.org/alsa-lib.git

ALSA API會(huì)調(diào)用ALSA driver,而driver的代碼肯定在linux內(nèi)核中。

alsa-lib中的很多常用功能,被做成了動(dòng)態(tài)鏈接庫(kù),例如:alsa-lib/libasound_module_pcm_pulse.so,這些鏈接庫(kù)的代碼在alsa-plugins中。alsa-plugins的git地址是:

git://git.alsa-project.org/alsa-plugins.git

aplay等ALSA工具的代碼在alsa-utils中,其地址如下:

git://git.alsa-project.org/alsa-utils.git

1.open操作

gst-plugins-base/ext/alsa/gstalsasink.c: gst_alsasink_open

這一步之后,進(jìn)入alsa-lib作用域。

alsa-lib/src/pcm/pcm.c: snd_pcm_open

alsa-lib/src/pcm/pcm.c: snd_pcm_open_noupdate

alsa-lib/src/pcm/pcm.c: snd_pcm_open_conf

alsa-lib中pcm有很多插件,提供諸如硬件、復(fù)制、線性變換等操作。詳見(jiàn)alsa-lib/include/pcm_plugin.h。

alsa-lib/src/pcm/pcm_hw.c: _snd_pcm_hw_open

alsa-lib/src/pcm/pcm_hw.c: snd_pcm_hw_open

alsa-lib/include/local.h: snd_open_device

這個(gè)函數(shù)調(diào)用open系統(tǒng)調(diào)用,進(jìn)入內(nèi)核空間。在內(nèi)核空間中根據(jù)driver模型的不同,進(jìn)入linux-kernel/sound/core/pcm_native.c: snd_pcm_open(ALSA)或linux-kernel/sound/soc/soc-pcm.c: soc_pcm_open(ASOC),注意這里的snd_pcm_open和alsa-lib中的snd_pcm_open名稱(chēng)相同,參數(shù)卻不同。

2.write操作

gst-plugins-base/ext/alsa/gstalsasink.c: gst_alsasink_write

這一步之后,進(jìn)入alsa-lib作用域。

alsa-lib/src/pcm/pcm.c: snd_pcm_writei

alsa-lib有兩種寫(xiě)操作:snd_pcm_writei和snd_pcm_writen。snd_pcm_writei表示寫(xiě)入交織的PCM數(shù)據(jù),而snd_pcm_writen表示寫(xiě)入非交織的PCM數(shù)據(jù)。

alsa-lib/src/pcm/pcm_local.h: _snd_pcm_writei

alsa-lib/src/pcm/pcm_hw.c: snd_pcm_hw_writei

這個(gè)函數(shù)調(diào)用ioctl系統(tǒng)調(diào)用,參數(shù)為SNDRV_PCM_IOCTL_WRITEI_FRAMES,pcm數(shù)據(jù)的buffer,放在snd_xferi結(jié)構(gòu)中,傳入內(nèi)核空間。

linux-kernel/sound/core/pcm_native.c: snd_pcm_playback_ioctl1

linux-kernel/sound/core/pcm_lib.c: snd_pcm_lib_write

linux-kernel/sound/core/pcm_lib.c: snd_pcm_lib_write_transfer

這里會(huì)有兩個(gè)分支,以下僅討論DMA方式的處理。pcm數(shù)據(jù)放在snd_pcm_substream.runtime->dma_area指向的緩沖區(qū)。open的時(shí)候,使用mmap做好snd_pcm_substream.runtime->dma_area和snd_pcm_substream.runtime->dma_addr之間的映射。底層驅(qū)動(dòng)只須操作dma_addr即可。

3.音量操作

音量操作雖然在Gstreamer和ALSA中都有,但彼此并無(wú)調(diào)用關(guān)系。Gstreamer中的音量調(diào)整是用軟件改變PCM數(shù)據(jù)實(shí)現(xiàn)的,可稱(chēng)為軟音量。與之相對(duì)的是音頻硬件功放經(jīng)揚(yáng)聲器所產(chǎn)生的音量,是為硬音量。ALSA的音量可以是軟音量,也可以是硬音量。

Gstreamer的音量操作步驟:

gst-plugins-base/gst/playback/gstplaysink.c: gst_play_sink_set_volume

這個(gè)函數(shù)主要是通過(guò)設(shè)置playsink的volume屬性來(lái)實(shí)現(xiàn)操作。

Gstreamer軟音量的實(shí)現(xiàn)代碼在gst-plugins-base/gst/volume/gstvolume.c中。

除此之外,還有流媒體音量設(shè)置gst_stream_volume_set_volume。詳見(jiàn)gst-plugins-base/gst-libs/gst/audio/streamvolume.c。

ALSA設(shè)置音量的代碼片段如下(注意,該片段沒(méi)有異常處理):

void SetAlsaMasterVolume(long volume) {long min, max;snd_mixer_t *handle;snd_mixer_selem_id_t *sid;const char *card = "default";const char *selem_name = "Master";snd_mixer_open(&handle, 0);snd_mixer_attach(handle, card);snd_mixer_selem_register(handle, NULL, NULL);snd_mixer_load(handle);snd_mixer_selem_id_alloca(&sid);snd_mixer_selem_id_set_index(sid, 0);snd_mixer_selem_id_set_name(sid, selem_name);snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);snd_mixer_selem_get_playback_volume_range(elem, &min, &max);snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100);snd_mixer_close(handle); }

ALSA的音量操作步驟:(只討論硬音量)

alsa-lib/src/mixer/simple.c: snd_mixer_selem_set_playback_volume

alsa-lib/src/mixer/simple_none.c: _snd_mixer_selem_set_volume

這一步將volume數(shù)據(jù)放到selem_none_t.str.vol結(jié)構(gòu)中。后面都是針對(duì)這個(gè)結(jié)構(gòu)的寫(xiě)操作。

alsa-lib/src/mixer/simple_none.c: selem_write

alsa-lib/src/mixer/simple_none.c: selem_write_main

alsa-lib/src/mixer/simple_none.c: elem_write_volume

alsa-lib/src/control/hcontrol.c: snd_hctl_elem_write

alsa-lib/src/control/control.c: snd_ctl_elem_write

alsa-lib/src/control/control_hw.c: snd_ctl_hw_elem_write

這個(gè)函數(shù)調(diào)用ioctl系統(tǒng)調(diào)用,參數(shù)為SNDRV_CTL_IOCTL_ELEM_WRITE,進(jìn)入內(nèi)核空間。

linux-kernel/sound/core/control.c: snd_ctl_elem_write_user

linux-kernel/sound/core/control.c: snd_ctl_elem_write

驅(qū)動(dòng)上層的數(shù)據(jù)放在snd_card.controls鏈表中。這個(gè)鏈表中的元素是snd_kcontrol類(lèi)型的。而驅(qū)動(dòng)底層使用snd_kcontrol_new類(lèi)型的數(shù)據(jù)。

在設(shè)備初始化時(shí),使用snd_soc_cnew或snd_ctl_new1函數(shù)從snd_kcontrol_new類(lèi)型的模板中,生成相應(yīng)的snd_kcontrol類(lèi)型的數(shù)據(jù)。snd_kcontrol_new類(lèi)型的數(shù)據(jù)可以用SOC_SINGLE、SOC_DOUBLE_VALUE之類(lèi)的宏生成,其默認(rèn)的put函數(shù)是snd_soc_put_volsw。

linux-kernel/sound/soc/soc-ops.c: snd_soc_put_volsw

linux-kernel/sound/soc/soc-io.c: snd_soc_component_update_bits

linux-kernel/drivers/base/regmap/regmap.c: regmap_update_bits_check

使用regmap技術(shù)映射I2C、SPI接口地址之后,即可調(diào)用相關(guān)函數(shù)修改相關(guān)音頻外設(shè)的寄存器值了。

總結(jié)

以上是生活随笔為你收集整理的ALSA(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。