ALSA Audio API 使用指南
此文档旨在提供一个对ALSA Audio API的介绍。它并非是一个API的完全参考手册,它也没有涉及许多特定的方面,很多复杂的软件会涉及那些特定的方面。然而它试着给一位合理的熟练的程序员提供足够多的相关知识和信息,而并非给那些使用API来编写简单程序的不熟悉ALSA的新手。
文档中所有的代码都遵循GNU Public License。如果你试图在其它的准则下使用ALSA来编写程序,那么我将建议你寻找其他的文档。
内容介绍
。理解音频接口
。一个典型的音频应用程序
。一个最简单的回放程序
。一个最简单的捕获数据程序
。一个最简单的驱动中断程序
。一个最简单的全双工程序
。如何使用API
。打开设备
。设置参数
。接收和传输数据
。为何你会要去忘记这里所讲述的
一、理解音频接口
我们先来了解下音频接口的基本设计。对于一位应用程序开发者,你不需要担心硬件水平如何操作,它们全部由设备驱动来搞定(这些驱动是由ALSA来提供的一些组件)。但是,如果你想写出高效和简洁的软件你必须要对它们有个概念上的了解。
音频接口是一种设备,该设备可以让电脑对外接收和向外发送音频数据。在电脑那一端,音频数据用一串比特流来表示,就像其它种类的数据一样。虽然如此,音频接口发送和接收音频数据即可以用模拟信号(时刻变化的电压)也可以用数字信号(一些比特流)。无论用什么来接收发送数据,电脑用来表示一段音频的比特流在往外传输前都要被转化为模拟信号;同样的,被声卡接收的外部信号在被电脑使用前也需要被转化为数字信号。这两方面的转化也是音频接口的用途所在。【注:raison d'etre为法语,意为:存在的目的或理由】
声卡内部有一个硬件缓存区域。当声卡接收到外界声音信号时,通过计算机它将信号转化为可用的比特流并存储在用来发送数据给计算机的硬件缓存中。当缓存存储了足够多的数据时,声卡中断计算机告知它数据已经准备好了。一个相似的过程将会发生在将数据从计算机传送到外界时。此过程中声卡中断计算机并通知它缓存有空间,计算机将会往里面存储数据。声卡接着将那些数据转化成所要求的任何格式并将其传送到外界,并且传输。有一点是十分重要的,那就是声卡循环使用这块缓存。也就是说,当到了缓存的末端时,会将开始的数据擦除用来存数据。
为了保证这个过程的正确执行,有一些变量需要设置。它们包括:
。当在计算机使用的比特流和外界使用的模拟信号之间转化时声卡要用什么样的格式?
。声卡的采样率是多少?
。当有多少数据时声卡才中断计算机?
。硬件缓存要设置为多大?
头两个问题是控制音频数据质量的基础。后两个问题影响着音频信号的延迟。这个术语涉及到以下两个方面的延迟
1. 数据从外界到达声卡与转化成计算机中可用的数据之间的延迟(称为:内部延迟)
2. 数据被计算机传输,并传输到外界的延迟(称为:外部延迟)
虽然一些程序不需要关心这两方面的东西,但对很多音频相关软件它们都十分重要。
二、一个典型的音频应用程序
下面是一个典型的音频应用程序的大致结构:
open_the_device();
set_the_parameters_of_the_device();
while (!done) {
/* one or both of these */
receive_audio_data_from_the_device();
deliver_audio_data_to_the_device();
}
close the device
三、一个最简单的回放程序
下面这段程序开启声卡回放,设置成双声道,16bit(采样位数),44.1KHZ,交叉存储,常规的读写(不用mmap)。然后传送一些随即的数据给声卡,退出。它也许反映了最简单的ALSA Audio API的用法,但它并不是一个真正可运行的程序。
四、一个最简单的捕获数据程序
这段程序打开声卡捕获数据,设置为双声道,16bit,44.1KHZ,交叉存储,常规的读写。然后读一些数据,退出。它并非实际运行程序。
五、一个最简单的驱动中断程序
这段程序打开声卡回放,配置成双声道,16bit,44.1KHZ,交叉存储,常规读写。它将等待声卡直到声卡准备好回放数据,同时传输一些数据给它。这种设计可以使你的程序很容易的通过一种回调驱动机制来和系统绑定,这样的软件比如:JACK,LADSPA,CoreAudio,VST等。
六、一个最简单的全双工程序
全 双工可以通过上面提到的回放和捕获设计来合并实现。虽然很多现有的音频程序使用了这种设计,但这篇文章中认为这是有很大缺陷的。上面的中断驱动样例在多数 情况下是一个很基本也很好的设计模式。然而,它在扩展成全双工时也是十分复杂的。这正是我为何要建议你忘记我前面所说的。
名词术语:
Capture
从外界获取音频数据(和“录音”不同,录音意味着将数据存储起来,它并不是ALSA库的API)。
Playback
将音频播放出来,使能被听见,这也许并不是必须的。
Duplex
捕获和回放在同一声卡同一时刻同时发生的情况
Xrun
一旦声卡开始运行,便一直持续直到被要求停止。它将收集数据给计算机使用并且(或者)发送计算机中的数据给外界。但有很多种情况你的程序并非可以控制声卡正常的进行。在回放的时候,当声卡需要从计算机中收到数据时,而此时并没有,xrun便可以强迫它使用在硬件缓存中留有的旧数据。这种情况叫做“下溢”。在捕获的时候,声卡也许要传送数据给计算机,但此时计算机没有空间来存储,因此,声卡会重写部分硬件缓存中没有及时送出的数据。这种情况叫做“上溢”。简单的说,我们用词“xrun”来概括其中的一个或几个。
Pcm
Pulse Code Modulation(脉冲编码调制)。这个词(还有缩写)描述了一种用数字化形式表示模拟信号的方法。这种方法几乎被所有的计算机音卡所使用,它在ALSA API中用“audio”来简称。
Channel
Frame
一个采样是描述某一时刻的单通道下一个信号点的声音信号的振幅的信号值。当我们谈及数字音频时,我们经常谈到的是代表所有通道的一个信号点的数据。它是单个通道采样的一个集合,叫做"帧"。当我们依据帧来表示一段时间时,它粗略的等于人们用一组采样来衡量,但前者更精确(???);更重要的是,当我们在讨论代表一个时刻所有通道的数据量时,帧是唯一能引起人们感官感受的标准。几乎所有的ALSA Audio API使用帧作为衡量音频质量的标准。
Interleaved
一种将同一时刻所有通道音频数据依次存取的交叉存储形式。参看:不交叉存储。
Non-interleaved
一种将每个通道的数据按顺序存储的存储形式,不同的通道的数据存储在另一个缓存中或者同一个缓存的其他地方。和交叉存储对比。
Sample clock
时 钟源,用来决定采样的传送,接收时刻。一些音卡允许你使用外部时钟,比如“全球时钟信号”(经常在一些工作室中使用),还有使用来自数字数据的时钟信号的 “自动同步信号”。所有的声卡内部都必须至少有一个采样时钟源,典型的是一种小的晶体时钟。一些声卡不允许改变时钟频率,一些则有不是很精准的时钟(比如,44.1khz)(???)。没有两个时钟能够以同一个时钟频率运行,如果你需要两个采样时钟进行同步,他们必须要和同一个采样时钟进行同步。(?晕了)
七、如何使用API
1.打开设备
ALSA将捕获和回放的用API分开。。。(估计是说用同一个api来实现了吧,没写了)
2.设置参数
上面提到了要使声卡工作需要设置很多的参数。然而,由于你的程序将不会实际的直接的去和硬件打交道,所以我们使用了两个不同的设置参数的方式来替带用设备驱动来控制硬件:
硬件参数
下面的参数可以直接影响声卡的硬件
采样率
如果声卡有模拟i/o的情况下,当声卡准备好了A/D或D/A转换时,这个可以控制声卡的速率。对于全数字的声卡,它控制用于移动数字数据进出外部的时钟的速度。在一些声卡中,其它的硬件指定设置也许意味着你的程序不能控制这个值(比如,当声卡用一个外部时钟源来决定采样率时)。
采样格式
这个控制了用于从声卡传输数据的采样格式。它也许和硬件直接支持的格式不符。
通道数
这个完全可以自定义。
数据接入和布局
数据接入控制了程序从声卡接收传送数据的方式。有两个参数来设置4种情况。一个参数是是否使用“读写”模块,该模块中有相应的用于传输数据的函数调用。另一个选项是用“映射模式”,该模式通过拷贝内存区域的数据来传输数据,这个API仅仅需要在开始和结束的时候注明一下即可。
数据布局是指数据的存储是交叉存储还是非交叉存储。
中断间隔
这个决定了读或写完整个硬件缓存需要发生多少次中断。它能根据一些指定的时间段来设置,也可以根据一段时间的长短来设置。设置决定了在声卡向计算机发出中断之前积累的空间中或数据中的帧数。它控制着延迟。
缓存大小
这决定了硬件缓存的大小。它可以用时间长短或帧数来指定。
软件参数
这些参数控制着硬件驱动的操作而不是硬件本身。很多使用ALSA Audio API的程序什么参数都不需要设置,一些只需要设置其中的一部分。
什么时候打开设备
当你打开声卡设备的时候,ALSA确认它并没有在被使用——没有数据正在传输。假如,此时,你想要开始数据传输,有几个选项需要设置。
此处的控制关键是开端,开端定义了自动开启设备所需要达到的空间/数据包含的帧数。如果为回放设置了一个非0值,那在设备开始运作之前就要先填充硬件缓存。如果设置成0,那么最开始写入数据给设备(或者试图开始捕获流数据)将会开启设备。
你可以用snd_pcm_start来明确的打开设备,但如果是回放的话要求缓存中预先填充数据。如果你没有预填数据而想开始回放,函数则会返回-EPIPE,表明现在没有数据在向硬件缓存中传。
Xruns有什么作用
如果xrun发生了,如果被请求了,设备将通过几个步骤来处理它。选项包括停止设备,用于回放的硬件缓存的全部或部分静音。
停止极限
如果可用的数据/空间的帧数达到或超过了这个值,设备将停止声卡。
静音极限
如果用于回放流的可用的空间帧数达到或超过了这个值,设备将往硬件缓存中填充静音数据。
静音大小
当静音极限到达时,这个值决定了往硬件缓存中写入多少静音数据。
唤醒所需的最小可用空间/数据。
使用poll(2)或者select(2)来控制音频数据的传输的程序可以设置这个值来控制在什么时候唤醒程序,这些时候与硬件缓存的状态相关。
传输块大小
这个决定了传入/出数据给硬件缓存时所用的帧数。
还有一些其他的软件参数此处没有提及。
接收和传输数据
没有写
八、为何你会要去忘记这里所讲述的
。。。