Linux的声音系统全接触

2008-1-4 13:34

从Linux控制台唤起你注意的简单的“丁”声,到DVD的环绕声,今天音频已成为桌面计算的重要部分。确实有许多计算机用户不需要声音,但是声音能够为许多计算机任务增色。正是如此,音频硬件已经成为一个几乎所有主板和操作系统,也包括大多数Linux发行版,的通用部件。

不幸的是,配置Linux的声音是一项让人头疼的事。在Linux中,有3套音频驱动,使用着两种不同的API。在这些驱动之上,还有几种支持库,目的是让程序员的日子好过一点,但对最终用户增加了配置的复杂性。实际上,对于一个普通用户,让系统发声会成为一项令人沮丧的经验。假如某个发行版没有正确地配置好声音,最终用户面对的将是寻找、安装和调试各种模棱两可、没有完善文档的设置选项。

作为对Linux声音系统的调查,让我们从对声音架构的总体认识开始。了解多种音频流如何混在一起同步发声也正日益重要。在这些话题的基础上,对于特定驱动的认识就显得很必要。声音设备文件以及它们的权限经常是发生问题的根源,所以我们也会谈到这个话题。此外,支持声音的库文件既可以是祝福也可以是诅咒,所以了解它们也很有帮助。在文章的结尾,当掌握了前面的基础知识,你可以测试和使用声音工具,并且设置常见发声程序的选项。

理想化地说,音频应用程序应该是直接了当的:发出一个命令或点击一个按钮,就可以听见预期中的声音。在这个情形的背后,Linux采用了几种层次的工具来发声,如图1所示。

声音数据在某个应用程序和声卡之间准确的传输路径,取决于该程序以及系统的整体配置,会有极大的差异。由于这个原因,追踪声音的问题也就非常困难。到底问题是出在硬件损坏、驱动程序的编程错误、库文件的错误配置、应用程序出错还是这些问题之间的相互作用呢?

声音库和应用程序都可以直接和声音驱动程序打交道或者依赖于其他的库。有些应用程序和库提供了多种选择:它们既可以直接使用驱动程序也可以通过其他的库来做。虽然图1还不很完备(还有数十个小的声音支持库),但已经涉及了许多最常用的工具和库,包括:

声音硬件 - 尽管在图1中只显示成一项,实际上有许多不同种类的声音硬件。如果没有支持你的硬件的Linux驱动程序,你可能该买个新的硬件。

OSS - 2.4.x版内核系列中,OSS的开源版本是标准的Linux音频驱动。4Front Technologies公司还提供商业版。对于软件来说,标准的内核OSS驱动和商业版OSS驱动没什么不同。多数Linux库和发声工具都支持 OSS。尽管2.6.x版本的内核中还包含OSS,但是它们已经正式被ALSA所取代。

ALSA - 高级Linux声音架构是OSS的替代方案。ALSA既兼容OSS,又提供了新的音频界面方法。ALSA作为2.6.x内核的标准配备,也能在编译成用在以往的内核上的模块。

ESOUND - EsounD是一个库以及后台服务,目的是无论使用OSS还是ALSA,它都为Linux音频系统提供一个统一的界面。EsounD还提供了一些底层驱动程序所没有提供的额外特性,例如支持多音频流同时发声(这个库有时也叫做esd)。

POLYPAUDIO - 这个库是意图取代EsounD的不速之客。

ARTS - aRts与KDE相联系的声音库。它能用EsounD、ALSA或OSS作为输出。你通过与之关联的后台服务使用aRts来产生对网络传输透明的声音,对于使用网络瘦终端来说会很方便。

SDL - SDL是一个游戏开发者常用的跨平台的多媒体库,它经常用名为libsdl的包安装在Linux系统中,它可以依赖于多种其它的库或者直接和声音驱动打交道。

声音应用程序 - 最终你的兴趣在于使用声音应用程序,例如XMMS。这些程序可能直接用到一种或多种的音频驱动,可能依赖于某个库,或者给你提供几种选择。

处理多音频流

Linux声音系统的一个烦人的方面在于处理多音频流。传统上,Linux声音系统是单线程的:如果某个程序在发声,别的程序就不能发声了。在某些情况下,这样会产生问题。

例如,假设你设置了让email软件在有新邮件到达时发声。如果你正在听一个OGG文件而有邮件来了,邮件程序将不能发出新邮件到达的提示声。随着越来越多的简单程序具备了发声功能,这种限制成为一个越来越严重的问题。

解决这个问题有两个办法:为音频驱动添加多线程支持和为音频库添加多音频支持。可以认为,为音频驱动添加多线程支持是最好的办法,因为直接使用音频驱动的程序无须修改。如果你的所有程序都使用同样的库,用库文件来处理这个问题则更快速,但是只要有一个程序是直接使用音频驱动的,这个好处就非常受限制了。

今天,许多ALSA驱动支持多音频流。然而,这种支持在一定程度上取决于音频硬件。同时,ALSA的OSS模拟对多音频流没有支持──使用OSS的程序享受不到这种好处,除非它想和使用了ALSA的其它程序竞争。OSS也采用了一些多线程的支持(常被称为多线程OSS)。EsounD、aRts和一些其它库也支持多线程发声。

从实用上说,你应该尽可能多地采用多线程的选择。假如一个程序能让你选择使用多线程的库还是直接使用不支持多线程的驱动,那么在所有可能情况下应选择用库。假如你可以在ALSA和OSS之间选择,而你的ALSA驱动支持多线程,则使用ALSA驱动。你可能无法设置每个程序都使用多线程的方案,但是你很可能能把大多数频繁使用声音的程序设置成多线程的。

启动驱动程序

驱动程序代表着Linux声音系统的核心。因此,编译和安装驱动是至关重要的。不幸的是,这个任务有时候看起来像是巫术。Linux的音频驱动是出了名的难伺候。在驱动程序层面的出问题的原因包括选错了驱动、不同种类驱动(ALSA和OSS)之间的相互干扰以及用了错误的驱动程序(通过错误的声音设备文件,很快会谈这个话题)。

首先你必须决定是采用ALSA驱动、内核OSS驱动还是商业版OSS驱动。为此,你应该在有关网站或使用内核配置工具查看你的硬件兼容性。假如你的硬件有多种驱动的支持,你得逐一测试以找出最好的那个。但是要小心 — 如果你试图同时直接把两种驱动加载到内核,最多只能是其中之一能够工作。要想逐个尝试,你需要编译两个内核或者把驱动编译成模块,这样就可以随你的意愿加载或卸载了。

假如你的系统已经有了基本的声音,最好不要改变配置,除非真有这个必要(例如,你因为别的原因需要重新编译内核)。

当挑选需编译的驱动时,选择“Device Drivers, Sound, Sound Card Support”这一选项。然后,在ALSA或OSS之间作出抉择并设定选项。

通常情况下,把声音驱动直接编译进内核比把它们编译成模块要容易得多,但是编译成模块会更有灵活性,因为你可以随意加载或卸载。编译ALSA模块时,要选择OSS兼容的选项(对于mixer功能和PCM功能都要选),因为许多程序编程时是直接使用OSS设备的,如果你不包含兼容层,它们将不能工作。假如你想使用商业的OSS驱动,你必须在内核设定基本的OSS支持,但是不要选择把你的声卡驱动编译进内核(最多只是把它编译成模块)。

一旦你重新编译了内核并用新内核重新启动之后,声音可能正常也可能不正常工作,这取决于你设的选项是否准确。如果你把关键功能编译成了模块,你需要加载它们。你可以用常用的命令,例如modprobe做到这一点。然而有些驱动需要在加载时设置特定的参数,ALSA就常有这种情况。请在ALSA网站查看详情,每种声卡都有所不同。典型情况是,你必须把几行alias命令加入到 /etc/modules.conf 文件中去。

声音设备文件

许多Linux驱动允许程序通过读写设备文件来使用硬件,这些文件存在 /dev 目录和子目录里。对于音频设备也是如此。不使用库文件的程序会直接使用设备文件,而使用了库文件的程序通过库文件间接地使用设备文件。

表1概括了对应OSS和ALSA的最重要的音频文件。这些设备文件依据它们的用途分属于几个范畴。(多数文件名以0或C0D0结尾。当你有多个声卡时,这些数字会变化,有些情形下会完全省略掉。)

表1: 重要的音频设备文件
设备类型 OSS ALSA
数字取样 /dev/dsp0 /dev/snd/pcmC0D0
Sun音频兼容性 /dev/audio0 N/A
混音器 /dev/mixer0 /dev/snd/mixerC0D0
高层音序器(high-level sequencer) /dev/music0 N/A
低层音序器(low-level sequencer) /dev/midi0 N/A
声音状态 /dev/sndstat N/A
控制文件 N/A /dev/snd/controlC0

对于大多数功能来说,最重要的文件是处理数字音频的输入和输出的数字取样文件,以及使调音程序能够控制音量的混音器文件。Sun音频兼容性提供了与Sun 工作站兼容的界面,对应于一些非常老的程序。音序器(sequencer)文件使你能播放MIDI文件,但不是所有的驱动都支持这个特性。状态和控制文件给声卡提供了信息和控制的界面。

早期版本的ALSA要求你运行一个叫snddevices的脚本来产生声音设备文件。这些文件在后期版本的ALSA应该是自动生成的,或者应该在多数现行的Linux发行版中默认建立。

尽管如此,假如你找不到适当的声音设备文件,你应该找找snddevices脚本并运行一下。

有个重要的细节是,打算使用声音应用程序的用户必须对设备文件有读和写的权限,至少对OSS风格的访问有这种权限。多数Linux发行版用两种途径之一来处理这个问题:或者提供一个具有写权限的组(例如audio或sound组),你可以把用户添加进去;或者把设备文件的所有权改成当前登录用户。前者会在用户远程登录并使用声音应用程序时产生冲突,而后者会在系统有多个用户登录时出问题(例如,你特地用多个用户名登录)。

安装库文件

许多程序依赖声音库,所以首先你必须安装这些库文件。幸运的是,如果你知道需要哪些库文件,这项任务是相当简单的,只要找到并安装适合你的发行版的软件包就行了。

库文件的部分问题在于,你不一定知道使用一个特定程序时的具体要求。有些程序在找不到所需的库文件时,会把一些选项隐藏起来。另一些不提供先决条件的说明,特别是当你从tar.gz格式(tarball)安装,或者是用其它绕过你的包管理系统的方法安装时。

然而,当通过RPM或用Debian的包来安装程序时,如果你试图安装的软件依赖于一个你还没有安装的库文件时,包管理工具会发出提示。在此情况下,你需要循着线索找到那个库。(有些包管理工具,例如APT,会自动帮你做这件事)

值得稍微详细地介绍一下Gentoo。由于它采用的是“全部自己编译”的方式,Gentoo让你在程序中明确包含或排除对特定音频库文件的支持──至少对于在编译时支持这些选项的程序如此。/etc/make.profile/make.defaults 文件包含了在可能情况下应该用到的所有库文件的清单,每个占一行。

假如你知道你不想用到某个库,比方说SDL,除非绝对必要,你应该在上述文件里面注释掉sdl这一行。你也可以在每次运行emerge时个别改动,通过加入库的名称以提供支持,或者在库名称前面加个“-”(比方像这样 -sdl)来忽略对这些库的支持。然而,这些选项只会在当这些库被列为软件包的“可选”(optional)库文件时才有效。

例如,如果软件包必需SDL才能正常工作时,在emerge命令中指定 -sdl选项将不起作用。你应该小心这些问题,因为可能造成程序的选项出现或消失。在某些情况下,它们还会影响到程序的音频质量。如果一个库比起另一个来,能更好地在你的硬件和程序上工作,你的选择就会影响到声音输出的质量。

为了得到这种控制权,在传统的二进制Linux发行版上,你必须用源码重新编译软件包,这么做要么干脆绕过包管理系统,要么用你喜欢的编译选项产生定制的软件包。

有些库提供了设置各种选项的配置工具。例如,aRts让你选择用ALSA、OSS还是EsounD(很快会更详细介绍)。你可能要看看库文件的文档来了解它提供了哪些选项。

测试和使用声音工具
所有的库文件和驱动程序安装之后,就可以着手测试声音了。做这件事,最好从最简单的工具入手 ── 即那些不依赖于驱动程序的。然后,再逐步向“上”测试用到不同的库文件的其它工具。

play
play命令直接通过OSS驱动(或者ALSA对OSS的兼容层)播放声音文件。例如,输入 play test.wav 来播放 test.wav。除了用 cat 直接发送一个声音文件到声音设备文件(这将极大地扭曲声音)之外,这是测试你的声音系统的功能和可操作性的最简单办法了。如果你使用了ALSA但是没能成功编译或加载OSS兼容支持,play命令将不起作用。

aplay
aplay在ALSA中的作用等同于play,用法也完全一样。如果你用ALSA,两个工具都应该试一下。如果aplay能用而play不行,通常表明你没能成功编译或加载OSS兼容支持。

esdplay
这个命令与play,aplay非常类似,只是它通过EsounD播放文件。

这些程序都只播放相对简单的文件,例如.wav文件。它们不能正确处理MP3、Ogg Vorbis或其它复杂的文件类型。

理想情况下,你能以普通用户的身份使用这些程序。然而,如果你在OSS设备文件上的权限不正确,你可能只能以root身份播放声音。果真如此,检查一下你的设备文件的权限然后再试试。

这些程序都有对应的录音程序:rec,arecord和esdrec。你应该能够用这些命令来录制一个声音文件。取决于你的混音器设置,生成的文件可能完全是空白的,即使你已经给了声卡一个适当的输入。

谈到混音器(mixer),这里需要注意一下,特别当你使用ALSA的时候。按照默认设置,ALSA启动时所有的输出频道都是静音的。因此,你可能能播放一个声音文件,但是却什么都听不到(播放程序可能暂时“冻住”了,但过了一会儿当文件静悄悄地播放完,又“解冻”了)。有很多种混音器程序,包括 mixer,amixer,alsamixer,kmix以及gnome-volume-control。前三个是文本界面的,其余是图形界面的。 amixer和alsamixer仅使用ALSA接口,其它的使用OSS接口或者两者都支持。图2显示了gnome音量调节程序。

你应该确保你所需的频道解除了静音并且音量调节滑块设置在恰当的水平(你需要通过试验才知道何谓“恰当”)。“Mater”和“PCM”选项对于放音至关重要。如果想播放音乐CD,你可能还需要设置CD选项。

为了录音,通常你必须对“Mic”(麦克风)或者“Line”选项解除静音。许多声卡提供了额外的选项,可能很重要,也可能无关紧要。例如,假如你只有传统的2个喇叭,环绕声的音量选项就不重要,然而如果你用了全套的环绕声系统则另当别论。

当重新启动计算机时,混音器的设置将被重置。为解决这个问题,你可以用一个能从文本文件中读入音量设置的文本界面的混音器。在本地的启动脚本中,如/etc/rc.d/rc.local,加入对这个程序的调用,或者从一个SysV风格的启动脚本中设置调用。

对于OSS来说,mixer程序是个好选择,但是你要从试验中找出最好的选项。详情请查看manpage。对于ALSA,一个捷径是用alsactl。这个程序能把当前的混音器设置存到一个文件中或者从文件中读出来。当你用自己喜欢的混音程序调节满意之后,用root身份输入 alsactl store 。这个命令将把混音设置储存到 /etc/asound.state 中。此后,你就能在一个启动脚本中调用 alsactl restore 来恢复设置(有些发行版的ALSA启动脚本已经包括了这个功能)。

除了简单的放音、录音和混音程序之外,还有许多更为复杂的音频工具。例如,xmms是播放Ogg Vorbis和MP3文件的常用程序,xine是播放MPEG流媒体的工具,当然,还有许多游戏也播放声音。事实上,声音已经用在许多你通常意识不到会放音的程序中。例如,大多数桌面环境,像KDE和GNOME,都能把声音和特定事件联系起来,比如说启动一个程序或控制台铃声。

设置 KDE/aRts 选项
许多应用程序和库提供了与声音有关的选项。这些选项你让你选择声音如何输出(直接通过驱动程序还是通过库),或者提供更精细的选项(例如时序选项)。如果你安装了多个声卡,你也许能选择想用哪一个。尽管将所有应用程序的所有选项罗列出来是不可能的,一些例子能让你建立起有哪些是能做的的概念。

我们来看看设置 KDE/aRts 选项和 XMMS 的选项。

KDE让你通过控制中心来调节输出选项(输入kcontrol命令或在菜单里选择)。这些控制实际上是设置aRts──KDE的声音库。这些选项位于控制中心的“声音和多媒体,声音系统”部分,见图3(有些发行版在名称上可能稍有不同)。

“General”标签让你设置有关网络可达性、CPU使用率已经自动挂起(auto-suspend)之类特性(当驱动程序不支持多线程,而且你也无法告诉aRts使用一个低层的多线程库时,最好是启用最后那个特性)。你也可以点击“Test Sound”和“Test MIDI”来测试aRts的设置(后者不是在每种声卡上都起作用)。

“Hardware”标签设置低层的选项。要特别注意的是“Select the Audio Device”按钮。你可以告诉aRts在几种低层的驱动和库中选择哪一个。典型的选项包括auto-detect,ALSA,OSS,Threaded OSS和EsounD。在不同的系统上,列出来的内容会有所不同,取决于安装的驱动程序和KDE编译时的选项。

默认设置通常是auto-detect,而通常也是可以接受的。然而,如果KDE应用程序(或其它使用aRts的程序)的声音质量有问题,或者KDE的声音特性与其它程序发生干扰,你可以试验其它选项。你也可以设置额外选项,例如取样率和质量。再一次,默认选项通常是可接受的,但是出问题的时候你也调整。

设置 XMMS 选项
作为一个专门的多媒体应用程序,与多数程序相比,XMMS提供了更多的音频选项。然而,这些选项并非完全是显而易见的,在 XMMS 菜单条上按鼠标右键并选择“Option,Preferences”,结果就是图4显示的 XMMS “Preferences”对话框。

XMMS 最重要的选项是“Output Plug-in”按钮,使你你选择输出驱动。通常你能在ALSA、OSS和EsounD之间作选择,然而准确的选项依发行版和安装的输出插件的不同而不同。

一旦你选择了要用的输出方式,你还能点击“Configure”机型微调。它会带来一个插件特定的对话框让你来设置其它特性。例如,用 ALSA 插件,你能选择要用的音频设备、启动或停止Mmap模式等等。

有时候,这些选项会对你听到的声音质量造成很大的影响,所以出现问题时,你应该尝试不同的选项。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License