【Alsa】播放声音跟录音详细流程
- 格式:doc
- 大小:14.57 KB
- 文档页数:5
alsa 命令流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!ALSA(Advanced Linux Sound Architecture)是 Linux 操作系统中的音频架构,提供了对音频设备的底层控制和管理。
Linux ALSA 声卡驱动的分析一、ALSA && OSS在linux系统中,先后出现了音频设备的两种主要框架:OSS和ALSA.针对不同的数字音频子系统,出现了几种微处理器或DSP与音频器件间用于数字转换的接口。
1.1 音频设备的硬件接口:(1)PCM接口。
(2)IIS(I2S)接口。
(3)AC97接口。
在CD,MD,MP3随身听多采用IIS接口,移动电话会采用PCM接口,具有音频功能的PDA则多使用和PC一样的AC97编码格式。
1.2 linux OSS音频设备驱动OSS标准中有两个最基本的音频设备:mixer(混音器)和dsp(数字信号处理器)。
在声卡的硬件电路中,mixer是一个很重要的组成部分,它的作用是将多个信号组合或者叠加在一起,对于不同的声卡来说,其混音器的作用可能各不相同。
在OSS驱动中,/dev/mixer设备文件时应用程序对mixer进行操作的软件接口。
1.2.1 OSS用户空间编程(dsp编程)对OSS驱动声卡的编程使用linux文件接口函数,dsp接口的操作一般包括如下几个步骤(1)打开设备文件/dev/dsp。
(2)如果有需要,设置缓冲区大小。
(3)设置声道(channel)数量。
根据硬件设备和驱动程序的具体情况,可以设置为单声道或者立体声。
(4)设置采样格式和采样频率。
(5)读写/dev/dsp实现播放和录音。
1.3 linux ALSA音频设备驱动1.3.1 ALSA的主要特点.(1)支持多种声卡设备。
(2)模块化的内核驱动程序。
(3)支持SMP和多线程。
(4)提供应用开发函数库(alsa-lib)以简化应用程序开发。
(5)支持OSS API,兼容OSS应用程序。
ALSA系统包括驱动包alsa-driver,开发包alsa-libs,开发板插件alsa-libplugins,设置管理工具包alsa-utils,其他声音相关处理小程序包alsa-tools,特殊音频固件支持包alsa-firmware,OSS接口兼容模拟层工具alsa-oss,其中只有驱动包是必需的。
ALSAAudioAPI使用指南ALSA Audio API 使用指南2009年10月25日星期日 22:13ALSA Audio API 使用指南此文档旨在提供一个对ALSA Audio API的介绍。
它并非是一个API的完全参考手册,它也没有涉及许多特定的方面,很多复杂的软件会涉及那些特定的方面。
然而它试着给一位合理的熟练的程序员提供足够多的相关知识和信息,而并非给那些使用API来编写简单程序的不熟悉ALSA的新手。
文档中所有的代码都遵循GNU Public License。
如果你试图在其它的准则下使用ALSA来编写程序,那么我将建议你寻找其他的文档。
内容介绍。
理解音频接口。
一个典型的音频应用程序。
一个最简单的回放程序。
一个最简单的捕获数据程序。
一个最简单的驱动中断程序。
一个最简单的全双工程序。
如何使用API。
打开设备。
设置参数。
接收和传输数据。
为何你会要去忘记这里所讲述的一、理解音频接口我们先来了解下音频接口的基本设计。
对于一位应用程序开发者,你不需要担心硬件水平如何操作,它们全部由设备驱动来搞定(这些驱动是由ALSA来提供的一些组件)。
但是,如果你想写出高效和简洁的软件你必须要对它们有个概念上的了解。
音频接口是一种设备,该设备可以让电脑对外接收和向外发送音频数据。
在电脑那一端,音频数据用一串比特流来表示,就像其它种类的数据一样。
虽然如此,音频接口发送和接收音频数据即可以用模拟信号(时刻变化的电压)也可以用数字信号(一些比特流)。
无论用什么来接收发送数据,电脑用来表示一段音频的比特流在往外传输前都要被转化为模拟信号;同样的,被声卡接收的外部信号在被电脑使用前也需要被转化为数字信号。
这两方面的转化也是音频接口的用途所在。
【注:raison d'etre为法语,意为:存在的目的或理由】声卡内部有一个硬件缓存区域。
当声卡接收到外界声音信号时,通过计算机它将信号转化为可用的比特流并存储在用来发送数据给计算机的硬件缓存中。
Linux系统中用ALSA驱动声卡流程详解一、什么是ALSAAdvanced Linux Sound Architecture 的简称为 ALSA ,译成中文的意思是 Linux 高级声音体系(这是我直译的,可能译的不对)。
一谈到体系就有点范围就太大了,所以ALSA不仅仅是包括对声卡的支持和驱动。
ALSA具有如下特征:1、对所有音频接口的高效支持,从普通用户的声卡到专业级别多路音频设备。
2、声卡驱动完全模块化设计。
3、SMP and thread-safe design。
4、开发库(alsa-lib)为程序设计提供了简单、方便,并且拥有有高级的效果和功能。
5、支持旧版本的OSS API 结口,能为大多数的OSS应用程序提供兼容。
OSS是一个商业性的驱动,OSS有一个简装本的代码已经移入内核和ALSA,其中alsa-oss就是。
OSS公司据说目前已经并不存在了。
我们没有必要用OSS 公司提供的商业版本。
用ALSA和OSS简装版足够。
二、关于硬件驱动驱动的必备基础1、如何查看硬件芯片在Linux操作系统中,所有的硬件都是以芯片组来区分的,品牌并不是最重要的。
硬件最重要的标识是芯片组。
所以您在讨论区求助的时候,只说硬件品牌,而不提供芯片组,大家是帮助不了您的,切记。
我们查看硬件的芯片组是的命令是 lspci -v 或者是dmesg,由于dmesg输出的信息不太多,不够直观。
所以经常用的还是lspci -v 。
也可以用lshal 获取。
最方便的还是lspci -v。
初学者还是用 lspci -v 更好一点。
我们运行lspci -v 后,如果查看声卡芯片组,发会现有类似下面的一段:2、系统内核版本[root@localhost beinan]# uname -r -m -p -i2.6.11-1.1369_FC4 i686 i686 i386上面的表示的是系统的内核版本,处理器架构等。
提示:如果您自己编译内核,还要安装kernel-devel (或 kernel-source),这个是在系统光盘或者映像文件中有带。
Alsa是Linux高级音频接口。
面对众多的音频设备,Alsa为Linux音频开发人员提供了一套标准的访问机制,使得音频开发变得十分容易。
不信?下面我们就利用它编写一个简单的录音/播音程序,不过这需要你有一定的计算机语言基础。
一个典型的音频程序应该具有以下结构:打开音频设备为设备设置读写参数向音频设备读/写音频数据关闭设备Alsa库为我们实现这些操作提供了丰富的接口。
首先让我们封装一个打开音频设备的函数:snd_pcm_t *pcm_handle;bool device_open(int mode){if (snd_pcm_open (&pcm_handle, “default” , mode , 0) < 0)return false;return true;}snd_pcm_open是Alsa库提供的打开设备调用函数,这里我们指定打开缺省的音频设备,并根据参数mode将设备置为录音或是播放状态,如果设备打开成功,pcm_handle便指向该设备句柄,我们用全局变量保存起来,方便以后使用。
第二步是设置参数,参数设置不当将会导致音频设备无法正常工作。
在设置参数前,我们需要了解一下各个参数的含义以及一些基本概念。
样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位。
通道数(channel):该参数为1表示单声道,2则是立体声。
桢(frame):桢记录了一个声音单元,其长度为样本长度与通道数的乘积。
采样率(rate):每秒钟采样次数,该次数是针对桢而言。
周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。
交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。
而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。
alsa音频编程简单的例子(总结)1.源代码安装alsa库,否则编译例子不会通过。
原文引用/share/detail/172892942.编译简单的播放和录音的例子。
引用原文/f?kz=8225093703alsa源码编译过程中的错误及应对/post-21.html[cpp]view plaincopyprint?1.实验本人都是在ubuntu11.04中验证通过。
/***************************************************************************第一部分*************************************************************************/昨晚帮群里人解决的问题,呵呵,严格的说,不是我一个解决的,还有大牛Felix的帮忙。
给人解决问题的过程,也是自己学习知识的过程。
有些新人,在安装ubuntu后,系统没有声音,多半是因为Ubuntu的“声音控制驱动:Alsa”没有正确识别出电脑的声卡。
这个问题的解决方法,虽然有点复杂,但还有值得去尝试的,毕竟没有人想在Ubuntu的世界里,过没声音的日子~解决方法:去Alsa的官方网站,分别下载3个声卡驱动控制程序安装包,来安装。
一.声卡驱动控制程序:Alsa的下载1.下载网站:/main/index.php/Main_Page这里,我们要下载的是,Alsa最新版本的3个安装包。
从上面的网页里面,右边就能看到有“Download a package”—“current version”字样。
注意:Alsa驱动是在不断更新的,我们要做的,就是从网上下载最新版本的,上面的网页位置,就直接提供最新版本的直接下载。
这次的教程,我以目前最新的:1.0.20,为例子来讲解。
可能当你看到这篇教程的时候,版本已经更新了(比如1.0.21,22,23这样)。
我在MTK平台下调试⾳频ALSA#硬件原理图因为是我们公司的项⽬,我就不能把完整的原理图给出来。
因为两个MIC不涉及机密,跟MTK的公版是⼀样的。
可以给出来⼤家看看。
这个MIC是⼀个数字MIC,直接输出的就是数字信号,接在MTK8167S的⼀个数字通路上。
#MTK⾳频通路框图嵌⼊式设备和平台关系很⼤,所以做什么平台⼀定要弄清楚平台设备的框图。
MTK8167s⾳频的框图如下不同平台的差异也有不同,不要硬套,需要确认清楚。
图⽚上看到很多通路没?这些通路⾥⾯的东西都是需要根据tinymix来设置的,当然也有其他办法设置。
#通过tinymix配置通路我们正常的tinymix查看配置39 BOOL 1 O00 I05 Switch Off40 BOOL 1 O00 I07 Switch Off41 BOOL 1 O01 I06 Switch Off42 BOOL 1 O01 I08 Switch Off43 BOOL 1 O02 I05 Switch Off44 BOOL 1 O02 I06 Switch Off45 BOOL 1 O03 I05 Switch On46 BOOL 1 O03 I07 Switch On47 BOOL 1 O03 I10 Switch Off48 BOOL 1 O04 I06 Switch On49 BOOL 1 O04 I08 Switch On50 BOOL 1 O04 I11 Switch Off51 BOOL 1 O05 I00 Switch On52 BOOL 1 O05 I03 Switch Off53 BOOL 1 O05 I05 Switch Off54 BOOL 1 O05 I07 Switch Off55 BOOL 1 O05 I15 Switch Off56 BOOL 1 O06 I01 Switch On57 BOOL 1 O06 I04 Switch Off58 BOOL 1 O06 I06 Switch Off59 BOOL 1 O06 I08 Switch Off60 BOOL 1 O06 I16 Switch Off61 BOOL 1 O09 I00 Switch Off62 BOOL 1 O09 I03 Switch On63 BOOL 1 O10 I01 Switch Off64 BOOL 1 O10 I04 Switch On65 BOOL 1 O11 I02 Switch On66 BOOL 1 O11 I05 Switch Off67 BOOL 1 O13 I15 Switch Off68 BOOL 1 O14 I16 Switch Off69 ENUM 1 AIN Mux INT ADC70 ENUM 1 DAIBT Mux MRG71 BOOL 1 I2S O03_O04 Switch Off72 BOOL 1 INT ADDA O03_O04 Switch On73 BOOL 1 MRG BT O02 Switch On74 BOOL 1 PCM0 O02 Switch Off75 ENUM 1 Left PGA Mux OPEN76 ENUM 1 Right PGA Mux OPEN77 ENUM 1 AIF TX Mux Digital MIC78 ENUM 1 HPOUT Mux OPEN79 ENUM 1 LINEOUT Mux OPEN80 BOOL 1 DMIC Data Gen Switch Off81 BOOL 1 AMIC Data Gen Switch Off82 BOOL 1 SDM Tone Gen Switch Offaiv8167sm3_bsp:/ #⾥⾯已经有很多开关了,我们要做的时候通过tinymix把in 和 out对接起来。
理解和使用Alsa的配置文件最近在做音频相关的驱动,使用到了Alsa。
过程中涉及到一些硬件的设置和测试,需要了解Alsa的配置文件的写法,稍微学习了一下,这里把自己的一些简单理解记录如下。
1 相关说明1.1 网站资源Alsa项目的官方网址:Alsa LIB API Reference:alsa-doc/alsa-lib/配置文件的语法:alsa-doc/alsa-lib/conf.htmlAsoundrc的官方说明文档:main/index.php/Asoundrc实际上,如果你仔细看了上述文档,大概也就没必要往下看我的文章了 8 )另:关于Alsa-Lib的API,网上的是每天自动生成的最新版本的API,如果你不能确认你使用的版本是否和最新版本完全兼容,可以看Alsa-lib包里自带的那一份文档。
可以在src包里执行make doc 自己build出来。
1.2 工作环境我测试的软件版本是基于Alsa 1.0.14的版本,当前最新的版本是1.0.16 (2008-7),不过配置文件这一部分应该是差不多的,至少从文档上来看是这样。
2 理解配置文件2.1 配置文件的位置配置文件的位置是由Configure阶段的选项来决定的,不过多数时候,Alsa的配置文件位于:/usr/share/alsa目录下,主要配置文件为/usr/share/alsa/alsa.conf 其它文件是否需要,位置在哪,都是由alsa.conf来决定的。
通常会有/usr/share/alsa/card 和/usr/share/alsa/pcm两个子目录,用于设置Card相关的参数,别名以及一些PCM默认设置。
此外,在alsa.conf中,通常还会引用/etc/asound.conf 和~/.asoundrc这两个配置文件,这两个文件通常是放置你个人需要特殊设置的相关参数。
按照Alsa官方文档的说法,1.0.9版本以后,这两个文件就不再是必要的,甚至是不应该需要的。
Tech Alsa驱动分析Guide目录1.ABSTRACT (3)2.INTRODUCTION (3)3.音频驱动框架介绍 (3)3.1音频设备的注册 (3)3.2音频驱动的注册 (4)3.2.1Probe函数的调用 (4)3.2.2Soc_probe函数 (4)4.通常的使用流程的分析 (6)4.1.1open过程介绍 (6)4.1.2snd_pcm_hw_params流程分析 (8)4.1.3prepare流程分析 (9)4.1.4write的流程 (15)4.1.5使用流程的总结t (18)5.AMIXE R调用的相关逻辑 (18)5.1.1Amixer调用的上层逻辑 (19)5.1.2Amixer的内核流程 (20)6.总结 (21)7.未讨论 (21)1. Abstract主要是讲2.6.21内核里面的alsa驱动的架构,以及在我们的平台上需要注意的东西。
.2. Introduction分成几个部分:驱动整体框架,一个简单的播放流程介绍,以及我们的平台需要注意的地方;3. 音频驱动框架介绍3.1 音频设备的注册这就是设备的注册了,设备本身非常简单,复杂的是这个设备的drvdata,drvdata里面包含了三部分,关于machine的,关于platform的,关于codec的,从大体上说machine主要是关于cpu这边的也可以说是关于ssp本身设置的,而platform是关于平台级别的,就是说这个平台本身实现相关的,而codec就是与我们所用的音频codec相关的;基本上这里就可以看出整个音频驱动的架构特点,就是从alsa层进入——>内核alsa层接口->core层,这里再调用上面说的三个方面的函数来处理,先是cpu级别的,再是platform的,再是codec级别的,这几层做完了,工作也就做得差不多了,后面会详细讲讲,当然这个执行顺序不是固定的(不知道是不是marvel写代码不专业导致的),但多半都包括了这三部分的工作;3.2音频驱动的注册3.2.1 Probe函数的调用前面讲了设备的注册,里面的设备的名字就是”soc-audio”,而这里的driver的注册时名字也是”soc-audio”,对于platform的设备匹配的原则是根据名字的,所以将会匹配成功,成功后就会执行audio驱动提供的probe函数soc_probe;3.2.2 Soc_probe函数这个函数本身架构很简单,和前面说的逻辑一样,先调用了cpu级别的probe,再是codec级别的,最后是platform的(这里三个的顺序就不一样),但是因为cpu级别的和platform级别的都为空,最后都调用了codec 级别的probe函数,也就是micco_soc_probe,这个函数基本上就完成了所有应该完成的音频驱动的初始化了;简单的划分,分成两部分,对上和对下:对上主要是注册设备节点,以及这些设备节点对应的流的创建;对下主要是读写函数的设置,codec本身的dai设置,初始化寄存器的设置,最重要的就是后面的control的创建和门的创建了,如下图所示:第二部分就是创建卡和流,对于alsa驱动来说,是先分成卡0,卡1…,然后对于每一个卡的每一个cpu支持的dai(digit audio interface)也就是pcm接口或者i2S接口等都要建立对应的流,一个dai有可能包含两个流,一个是录的一个是play的,但在我们的平台上对于i2S的dai是没有录音功能的,所以我们的平台只有一个卡,三个流,pcm的录和play,i2S的play;流的创建还是更多的考虑为上层服务的,它所提供的接口都是soc层的,这里非常重要的地方在于驱动的一个典型做法那就是如何把关键的内核数据结构和export到外部的/dev下的设备节点实现关联,比如:关键数据结构struct snd_pcm,是根据cpu所固有的dai创建的,而对于每一个struct snd_pcm又可能用到两个substream(它们实现具体的流的播放等),它们之间的链接是通过它的内部数据成员struct snd_pcm_str streams[2];来连接的,而这个snd_pcm类型的指针是在函数snd_device_new里面通过device_data放到设备里面的,这个设备会在snd_device_register_all的时候注册到/dev下面,并且调用dev_set_drvdata(preg->dev, private_data);来把这个指针放到设备的私有数据里面;而在需要使用的时候通过snd_pcm_playback_open里面的snd_lookup_minor_data函数取得其私有数据并返回的,这样就实现了设备节点和对应的驱动的数据结构的关联,这是一种非常普遍的做法;有了这个数据结构它就可以根据一定的原则取得对应于这个需求的substream,于是一切的操作都可以交给这个substream了;第三部分就是control的创建,这个函数比较简单,就是把表micco_snd_controls里面已经定义好的controls 模板创建controls,然后加入到card的controls列表中去;本身功能很清晰,但是对于我们平台来说,需要非常小心,因为这里决定了各个controls的序号,而这个序号是audio_controller访问硬件的索引,所以千万要小心尽量要维持目前的controls的序号,如果要额外添加新的controls一定要记得要放在micco_add_widgets后面来做,这样可以做到兼容,否则audio_controller的工作量就大了!第四部分就是门的创建了,这个函数也是很清楚,就是把codec对应的门都加入到codec->dapm_widgets 列表中去(这里的门的概念可以简单的理解为水管与水管之间的连接的地方,声音数据像水一样从水管里面流出来,源头可以是CPU了,也可以是modem,然后通过不同的门,流向不同的地方,比如speaker,比如蓝牙耳机等等),然后根据micco_audio_map把所有可能连在一起的门连接起来,这个表micco_audio_map的意思是{目的名字,控制点名字,源头名字},然后函数snd_soc_dapm_connect_input 会根据这些名字去查表codec->dapm_widgets(先前已经把所有的门都加入了)找到它们再根据不同的类型做不同的连接,比如是mux之间的连接,mux和pga之间的连接等等,注意这里的连接其实只不过是说找到连接的可能性,它对于不同的门,找到其可能的source和sink,加入到对应的列表中去,具体细节如下:首先,扫描整个codec所拥有的所有的门,如果它的名字和传入的sink的名字相同,则认为它就是这个路径的sink,如果它的名字和传入的source名字相同,则认为它是这个路径的source,如果源头或者sink没有找到都返回错误;然后分配一个struct snd_soc_dapm_path,这个数据结构的主要成分包括名字,source门,sink门,这条路径的control,这个源头和sink是否已经连接,是否已经走过(用在后面),这个数据结构会被挂在三个链表里面,一个是source的就是这个门会在很多的路径中,把它在这个路径中做source的path都连在一起,一个是sink的就是把这个门在所有这些由它做sink的path都连接在一起,一个是把所有的路径都需要连接在一起的这个是通过codec的dapm_paths来访问的;list_add(&path->list, &codec->dapm_paths);list_add(&path->list_sink, &wsink->sources);list_add(&path->list_source, &wsource->sinks);需要注意的时候,这里把路径的list_sink加入到了wsink门的sources列表里面,而把路径的list_source加入到wsource的sinks列表里面,所以当访问的时候从wsink门的sources出发就可以找到连接这个门作为sink的所有的路径,而从wsource的sinks列表出发就可以找到所有以这个门作为source的路径;第三步就是为这个数据结构赋值:source,sink,初始化三个链表;第四步:如果control为空则把这个路径加入到相应的三个链表中去,并且路径设为已经连接,并返回;第五步:否则,根据sink的类型,如果是adc,dac,input,output,micbias,vmid,pre,post,则把路径加入到三个链表,设置已经连接的标志;如果是snd_soc_dapm_mux则调用dapm_connect_mux来处理;如果是mixer和switch则调用dapm_connect_mixer来处理,如果是hp,mic,line,spk,则把path加入到三个链表中去,但是设置成为连接的状态。
【Alsa】播放声音跟录音详细流程
播放声音和录音详细流程
一,前言:
linux中,无论是oss还是alsa体系,录音和放音的数据流必须分析清楚。
先分析alsa驱动层,然后关联到alsa 库层和应用层。
二,链接分析:
1)链路一
usr/src/linux-source-3.0.0/sound/core/pcm_native.c文件中注册部分.mmap = snd_pcm_mmap调用
snd_pcm_mmap_data(substream, file, area);
该方法中进一步调用
substream->ops->mmap(substream, area);
根据./soc/pxa/pxa3xx-pcm.c文件中.mmap =
pxa3xx_pcm_mmap,可知
dma_mmap_writecombine(, ,runtime->dma_addr,);函数被调用。
soc/pxa/pxa3xx-pcm.c文件中
pxa3xx_pcm_hw_params()函数会创建链表,根据dma_buff_phys = runtime->dma_addr;
dma_desc->dsadr = dma_buff_phys;可知
runtime->dma_addr为dma内存端地址,且此地址由alsa 库层传递进来。
又根据
dma_desc->dtadr = prtd->params->dev_addr
和soc/pxa/pxa3xx-ac97.c文件中
.dev_addr = __PREG(PCDR),可知dma外设端地址为ac97控制器中fifo读写寄存器PCDR。
至此,第一条链路建立完毕:FIFO通过DMA和内存交互。
2)链路二
ac97接口或者i2s(Inter—IC Sound)或者pcm接口可以将cpu和codec(wm9714/alc5620/alc5621)连接起来。
配置好格式:pcm接口必须配置采样率、采样位数、通道数和传送格式;
i2s接口必须配置采样率、采样位数、通道数和对齐方式;
ac97接口比较灵活,可以认为cpu这端不用配置,只需要在codec端配置就行了。
当然,电源、时钟、IO任何数
字芯片都得配置。
最后不能混淆数据接口和控制接口的慨念,i2s和pcm只能传输音频数据,访问codec的寄存器必须通过i2c等控制接口,ac97接口分时传输控制和数据。
codec 中的adc/dac通过ac97等接口同cpu的fifo交互数据。
第
二条链路建立完毕。
3)链路三alsa_lib源码中pcm.c文件中
snd_pcm_readi(,buffer,size)调用pcm_local.h文件中
_snd_pcm_readi(,buffer,size);
进一步调用
pcm->fast_ops->readi(pcm->fast_op_arg, buffer, size);
根据pcm_hw.h文件中.readi = snd_pcm_hw_readi可知,ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES,
&xferi);被调用。
内核中,根据/soc/pcm_native.c文件中.unlocked_ioctl = snd_pcm_capture_ioctl,可知snd_pcm_capture_ioctl1被
调用,根据SNDRV_PCM_IOCTL_READI_FRAMES参数可知snd_pcm_lib_read(substream, xferi.buf, xferi.frames);被
调用,
最终
snd_pcm_lib_read1(,,,,snd_pcm_lib_read_transfer)被调用。
根据transfer被调用可知snd_pcm_lib_read_transfer被调用,然后调用copy_to_user(buf, hwbuf,
frames_to_bytes(runtime, frames)),可知,将dma端内存
的数据拷贝到alsa_lib提供的一个指针所指的内存,alsa库函数snd_pcm_readi、snd_pcm_writei实现了内存到内存的交互,或者近似地认为是内存到音频文件的交互。
至此最后一条链路建立完毕。
三,执行分析:
录音:mic phone接到codec,经过adc变成数字信号,经过链路二中ac97等接口存储到cpu的fifo中,经过链路一中的dma传输存储到内存,经过链路三中alsa_lib中
snd_pcm_readi接口传给录音软件,经过编码,进而形成音频文件。
放音:播放软件将音频文件解码,并通过链路三中
snd_pcm_writei接口逐渐传递到和dma相关的内存,经过链路二中dma传递给cpu的fifo,再经过ac97等接口传递给dac,最后传给连接在codec上的speaker。
四,总结:
1)ac97(声卡标准)数据传输颇复杂,分时复用,cpu 端fifo和codec端adc/dac关系要对应好。
比如,cpu端的pcm left fifo占用slot3(CPU中扩展插槽),那么adc(Analog to Digital 模数变换)只有配置成slot3才能把数据传递给它,如果配置成slot6,那就传给cpu的mic in fifo了。
录音单声道通常选择slot6,录音双声道通常两个adc分别选择slot3和slot4。
2)wav音频文件大小计算:要测试录音是否丢祯,就必然要计算文件大小,通常的方法是:根据录音时间,用公式:
录音时间(单位s)x采样率x(采样位数/8)x通道数。
比如:录音时间5秒,采样率8kHz,位数16位,通道
数1,那么5x8000x(16/8)x1=80k,实际的wav文件大小稍大于80k就对了。
还有一种计算文件大小的方法:通常音频系统要用dma,也会用到dma中断,可以在dma中断中打印计数,次数xdma中断周期字节就行了。
3)数据交换的大小问题:
链路一中DMA传输必须和FIFO的特性匹配:若FIFO 位宽是16位,深度是16,并且半满时向DMA发出请求(握手),则链表式DMA必须配置成传输位宽16位,1次突发16字节,才能保证不丢失位数和数据个数。
链路二中cpu端FIFO位数要和codec端adc/dac采样位数匹配,i2s/pcm接口可以配置成一样的值,比如16位,ac97接口复杂一点,cpu端不用配置,那么采样位数是多少呢若cpu端fifo一个声道位宽16位,codec端adc/dac位宽18位,ac97通道20位,则传输到fifo端就被截取到有效的16位,整体采样位数16位,adc/dac的性能没有充分发挥而已。
链路三中snd_pcm_readi、snd_pcm_writei函数第三个参数表示读写数据的大小,单位是帧,不是字节。
双声道16位格式一帧大小为4字节。