momo zone

调核人的blog

linux音频系统的那点事

这几年linux 音频架构层面上演着一出又一出的闹剧,你方唱罢我方登场。每次发行版更新时声称某某架构解决了某某问题,提供了某某特性,表面看起来是在解决问题,其实则是混乱不堪,让一般用户无所适从。音频这块可以说是就像是泡久了的面条一样找不到头绪。

从原本的单纯声卡驱动OSS ,到重新发明轮子的alsa 。这期间的一系列变化以及alsa的不足导致了大量应用程序不得不反复修改来对付这一系列的糟糕变化。OSS的单纯(仅仅用来驱动硬件,不涉及混合器和复杂的API)是基于早期类似声霸卡这样的玩意,这是一套完备独立的音频硬件,具备了硬件混音器。 后来intel 搞出来了AC97 ,以及后来的HDA ,一切变得复杂起来了(当然主要是成本也低了):声卡变成了软声卡,或者与其说是声卡不如说是几个音频D/A+一堆底层API(在windows的AC97或HDA驱动中),也就是说这些低端玩意都不具备硬件混音器,这些功能都抛给软件去做了。当然也就有了相对比较大的延迟,并且特效也要软件去做了。

OSS是朴素的,设计也是遵循经典的linux 设备驱动模型,看到/dev出现了一个个音频设备,一切都不是那么迷茫。ls >/dev/dsp 是发出的噪音让人意识到“让这个玩意发音太容易了”。 到了alsa的时候就没那么幸运了,设备开始变得看不到摸不着,驱动开始像保姆一样既在内核里面插一腿又在应用层环境里自做主张而且还试图模仿(模拟)OSS。更糟的是音质的问题十分严重。而且混音器工作得并不好。

然后就是八仙过海各显神通的时代了,为了解决多音频流问题,各个桌面环境都提供了一系列的声音服务(aRts和ESD),这些服务都是各自为战,用尽各种曲线救国的方法掩盖linux音频系统的种种缺陷。这些设计连同alsa自身的很多方面都严重背离了linux系统设计的原则。

这里有篇文章详细介绍了linux音频架构的混乱,后一篇则是近段时间写,讲了一下这方面的近况,并毫不避讳的对OSS V4 大大赞赏。

Linux音频系列之一:ALSA是垃圾,OSS王道!

翻译自
http://insanecoding.blogspot.com/2007/05/sorry-state-of-sound-in-linux.html被墙,请用www.sneakme.net。一个有广度和深度的评论。我觉得我们真的应该思考一下这个问题。
– 事情从什么时候开始变得糟糕的。。。
– ALSA怎么了,为什么突然开始使用这么个文档不良的东西。。。。
– 我们应该支持闭源吗?不过,这篇文章是两年以前写的,现在,事情已经变了。另一篇博文:
http://insanecoding.blogspot.com/2009/06/state-of-sound-in-linux-not-so-sorry.html
分析了当前Linux声音系统的现状。翻译随后奉上。Linux声音系统的可悲境地
作者:Insane Coding
日期:2007-05-17

我们先谈谈背景吧。

回到过去的日子里,如果你有一台PC,那么,只有一种卡可以称为“声卡”,它叫做Sound Blaster16,通称“声霸16”。如果你玩当时流行的游戏,你会发现它们很多都只支持这种声卡。其他声卡公司要想赢得一点点声卡市场份额,就必须提供“声霸”模拟器。有时候,这种模拟器很bug,但是,你要是不买来,你也根本不知道它到底有没有bug。所以,如果你真的想有好的音效,你只能老老实实买“声霸16”。

回到Linux刚刚问世的时候。那时候,PC机大多数都是386,当然,也只需要那一种声卡。可以理解,在早期Linux中,“声霸”的支持那是相当的完美阿!不仅如此,因为Linux的API很好很强大,而且大多数的Linux声音软件都对应这一种API,所以,其他声卡的厂商都用同样的API提供Linux驱动程序。从此,这种Linux系统的“声霸”API被称为“Linux soundAPI”,各个厂商的声卡驱动器都被整合在了同一个软件包中,这个包后来称为“Open Sound System”,简称OSS。

因为OSS是面向Unix的,而且很好很强大,其他UNIX操作系统那时也有了声音支持的需求,OSS因此也被移植到这些系统上了。今天,OSS在几乎所有的UNIX系统上都能运行(不包括Mac OS X,但包括Linux, *BSD, Solaris以及AIX和HP-UX等等)

现在,站在开发人员的立场上,如果你想编一个简单的程序,包括声音支持,而你又想让你的程序在各种UNIX系统上都能跑,你的选择很简单:只要用OSS编写代码就行了,一切都很好,很容易移植。

但是,OSS有一个致命的缺点,即:混音。比如,你想同时听音乐和新闻,新闻音量很大而音乐很安静,那么调整音量就很费劲了。但是,当OSS最初被设计的时候,它就把“混音”的工作转移给了声卡,当时的声卡允许多路输出混合。但是,更多新的声卡决定跟随modem的脚步:把混音工作交给软件。从此以后,声卡的各个功能都必须用软件来书写,而“混音”常常被忽视,而它实际上也不总是那么简单。从此,很多新的声卡在OSS下都具备混音功能。

因此,出现了两个新的声音系统:aRts和ESD,分别被KDE和Enlightenment/GNOME广泛应用。它们具有新的API,在声音被送往OSS之前就完成了混音。它们都期待新的程序使用它们的API。现在,我调研了aRts和ESD两者:aRts看上去很容易使用,甚至比OSS还要易用,我用5分钟就用aRts书写了一个声音播放器。ESD看上去比aRts提供更多的功能,但是比aRts复杂的多。如果你用上述两者之一写了程序,你可以运行多个实例,每个实例都用它们之一播放声音,你能听到所有的声音。

aRts和ESD的问题在于,它们是两个,所以,虽然大多数KDE和GTK程序都能使用其中一个或另一个,但是你不能同时使用它们两个。你只能一次使用一个,这是因为OSS的混音问题。甚至,它们之一也不能与另一个直接使用OSS的程序一起工作。为了解决这个问题,库封装器出现了。

第一个是Simple DirectMedia Layer (SDL),它封装了OSS,aRts,ESD甚至Windows和Mac OSX的声音系统。因为它在哪里都能工作,在UNIX上可以使用任何一种声音系统,听起来好像很容易移植。不幸的是,SDL只提供一种回调式的接口。虽然这对很多程序来说都不错,但是有时候会惹麻烦,比如在一些可以即时生成声音的程序中,不仅很难正确地编程,甚至会使得一些声音根本无法同步。

另一个是libao也封装了OSS,aRts,ESD和一些UNIX特有的声音引擎。libao的API也很易用,和aRts很像,我不用花什么事件就弄出了一个libao的程序。不幸的是,libao好久没有更新了。而且他的一些封装器也很buggy。libao只支持阻塞音频,也对即时生成声音的程序造成了麻烦,强迫程序使用线程,希望其中一个运行的时候另一个不陷入长眠,还要用信号量和互斥锁。

因为libao总的概念是好的,所以MPlayer团队使用了libao,消除了很多局限性,更新了,修正了bug,增加了更多的声音封装器,甚至包括两个Windows的和一个Mac OSX的,把新的库称为libao2。用MPlayer,你可以选择声音封装器,只要用-ao命令行选项就可以选择使用哪个系统了,也可以通过配置文件,永久地设置。我甚至拿了一些libao2DirectSound的代码,用于一个Windows应用程序,一个我认识的微软程序员看了看这个代码,说这个代码很好很强大,它展示了其封装器代码的质量。不幸的是,libao2与MPlayer结合紧密,里面包括各种各样的MPlayer库的调用,这对于将其应用于其他程序而言,是一个很大的不利因素。也许一些MPlayer或者库的开发人员可以聚在一起,把它们两者分开,把特需的特性作为插件,这样我们应用程序开发人员可以真正拥有一款可移植的声音库了。这也可能让MPlayer在更加古怪的驱动程序上播放声音,因为一个完全不懂MPlayer的开发人员也可以来修正这个bug。

当程序员们正在为他们宝贵的程序库而担忧的时候,OSS的开发人员们决定走闭源路线,为付费用户提供一些额外的功能(一般用户很少会用到)。这引起一片哗然,一些Linux开发人员决定创造另一个解决方案。

但是,他们既没有从核心开始重写OSS,也没有使用封装器(当然,用封装器解决不了混音问题),也没有基于已有的开源的OSS继续写,而是因为一些荒诞的理由,决定重写一个完全不同的API。这被称为Advanced Linux SoundArchitecture,简称ALSA。这个新的API很肥硕,而且基本没有文档,难以置信地复杂,与OSS完全不同。这就意味着,现有的驱动程序不得不为ALSA完全重新编写,甚至应用程序也要重写(或者让一些封装器,比如SDL和libao,支持ALSA)。

ALSA的优势是它具有一个软件混音器(但不总是能工作)。但是,显而易见,应用程序不会一夜之间全都转而使用ALSA。而且,ALSA不可移植,那些要支持BSD和Solaris的人还是要用OSS。也就是说,想要支持ALSA,就必须同时支持OSS和ALSA。因为OSS也能在Linux上用,我们为什么还要这么做呢?意识到这个,ALSA的开发人员在ALSA中加入了OSS模拟器。因此,明智的程序员只需要为OSS编程。但是,一个让人尴尬的地方是,使用ALSA的OSS模拟器比直接使用ALSA效果更好。很多SDL和libao的用户都说,用ALSA的OSS模拟器的话,声音的裂缝比起直接用ALSA来说更少。

但是,由于某些很傻的原因,ALSA的OSS模拟器不支持混音,结果直接使得ALSA的优势荡然无存。我这里有两块同时支持ALSA和OSS的声卡,结果,在OSS下工作的更好。更让我震惊的是,我发现声卡中具备硬件混音器,它并没有被ALSA的OSS模拟器利用,这就使得用ALSA的OSS程序根本没有混音。但是,因为某些原因,我却听到了大量的宣传,说我不得不把我的所有程序改成ALSA的,因为OSS被废弃了(英语叫deprecated)。我真的怀疑到底是不是因为ALSA的存在而使得FreeBSD突然废弃了OSS。一个可移植的框架,怎么可能因为一个鼠目寸光的操作系统不知道今后怎么做,而被废止呢?使用不可移植的API才是真正应该被废止的!我很聪明地把所有支持ALSA的宣传重定向到/dev/null中,但是,真正让我恼火的是,我的笔记本的内置声卡只支持ALSA。对于这些宣传,我更郁闷的是,如果ALSA更加得寸进尺怎么办?现在很多Linux发行版自带了SDL却没有OSS绑定,这已经很烦了,还能更糟糕一点吗?

现在,我的一个朋友最近决定改用Linux,因为他意识到了Linux在很多对他重要的方面都比Windows好的多。因为他的笔记本很新,它唯一能找到的驱动是ALSA的。现在,因为这个原因,他的笔记本声音一直很糟糕。音量控制很烂,强迫它回到Windows,那样能让声音正常一些。

这周初,另一个朋友告诉我,闭源的OSS自从上一个开源的OSS被加入Linux内核一来,一直在被更新,现在可以免费从它的网站上下载,安装,而且比ALSA更好。它甚至提供ALSA模拟器。这听起来很吸引人。我登录OSS的网站,把OSS安装到我朋友的笔记本上看看能不能解决问题。现在,你看,你听,声音清澈,音量控制细致得多,音量还能调到比ALSA更大[这真的是feature吗?不是bug?不会失真?译者注]我开始研究闭源的OSS,发现,它有一个软件混合器,甚至软件重采样都工作得很好。我然后把它安装到我自己的笔记本上,声音好多了。因为我目前只有一个程序是仅支持ALSA的,我不太在意,但是让我郁闷的是,这个程序的上一个版本还支持OSS呢。

一切都说明,ALSA就是个垃圾,从根上就是个坏主意。如果你想在Linux下得到好的声音支持,最好的,有时候也是唯一的选择,就是用闭源的OSS。用它,你总能够获得混音支持(甚至可以用ALSA做不了的硬件混音),支持很多UNIX操作系统,还有良好的音量控制。它还增加了一些改进的API,使得程序员可以做更多的高级音频功能。它还支持spdif,甚至你可以直接把AC3音频格式直接送入OSS,而不必先解码。

真正的问题是,它是闭源的,这使得很多人望而却步。但是,就像最好的Linux视频驱动是nVidia的一样,最好的音频驱动是闭源的,也不是什么奇怪的事情。因为我永远要在我的笔记本上得到最好的应用,而不是在乎什么奇怪的意见,只要闭源驱动工作得好,我就会使用闭源驱动。但是,对于我的发行版的打包着来所,它们就不得不避讳闭源软件了。虽然,对于nVidia和ATI的情况而言,程序员用OpenGL或X11写的程序也能被闭源驱动支持,程序员因此不必太在意用哪个来写。但是,对于OSS来说,如果发行版使用了完全不兼容的接口,而且提供SDL而不提供OSS,我们就不能使用闭源驱动了,我们的自由也没了。我们也就不得不使用垃圾,牺牲了好的可移植性。

我们必须鉴定我们的立场,把ALSA的宣传掐死在摇篮里,然后无条件地开发大量的不支持ALSA的应用程序,然后告诉ALSA的卫道士们让他们觉悟。我们必须让发行版们继续支持OSS,如果它们真的想要一个新的声音系统,它应该使用和旧系统相同的API,使用和其他UNIX一样的本地声音系统。

现在,我希望OSS再次开源,也许我们应该直接与4Front公司讨论,或者我们重新创造一个和闭源驱动具备同等质量的新的声音系统。但是,无论如何,我们都不能把我们所有的精力都浪费在那个破烂、不兼容、不可用的垃圾上了。

http://4front-tech.com/hannublog/?p=5
看看这个链接,你就更了解最新的闭源OSS了,也就了解为什么我们应该用它了。

综上,如果你遇到声音问题,你应该试试官方的OSS,让大家知道,OSS才是王道,ALSA是垃圾。也记得告诉你的发行版,ALSA是垃圾,它们不应该移除OSS。如果我们愿意,我们就应该有使用闭源驱动的自由。告诉应用程序的开发着说你需要OSS支持,告诉那些想要ALSA的你的应用程序的用户说ALSA是垃圾,并告诉它们,如果遇到问题,请用闭源OSS驱动。我们也应该考虑与4Front交涉,让它们重新将OSS开源,或者更新原有的开源OSS实现(或者干脆重写)。我们也应该吧libao2弄得更像一个库。如果我们采取这些措施,我认为,Linux的声音的形势,以及其他UNIX操作系统的形势,都会好得多。如果我们采取了以上必要的措施,UNIX声音程序就不再会沦为声音程序社区的笑柄。

Linux音频系列之二:不是那么可悲了

现在,Linux的声音现状不是那么可悲了这篇可以说是上一篇文章的对应。
这里还有一些问题值得思考:
* 延迟究竟是什么引起的?真的是封装的层次越多,延迟就越大吗?看看这篇:
* 最好看看原文后面的评论,也指出了原文的一些问题。
http://0pointer.de/blog/projects/pulse-glitch-free.html原标题:State of sound in Linux not so sorry after all.
原文:http://insanecoding.blogspot.com/2009/06/state-of-sound-in-linux-not-so-sorry.html
原作者:INSANE CODING大约两年前,我写了一篇文章,题为“Linux声音系统的可悲境地”(链接:http://insanecoding.blogspot.com/2007/05/sorry-state-of-sound-in-linux.html ) ,希望通过它让一些Linux下的声音问题修正。现在,两年过去了,很多东西都改变了,今天终于到了回顾Linux声音的现状的时间了。上一篇文章的总结(怕你没看过):
* Linux下的声音系统的历史很有意思,以前,硬件缺乏的“混音”功能大多数由软件来补充。
* 人们创造了很多“声音服务器”以便解决“混音”问题。
* 人们创造了很多“库”来解决后端太多的问题。
* 在Linux内核源代码中,ALSA替代了OSS v3,试图解决一些已有的问题。
* 闭源的OSS很好很强大。
* Linux发行版渐渐开始移除基于OSS的程序,以更好地向ALSA转移
* 一般的声音软件开发人员更喜欢简单的API。
* 可移植性是好东西
* 在某些情景下,用户会遭遇问题。

现在,很多东西都变了。比如:
* OSS再次开源和自由了。
* PulseAudio广为流传。
* 现有的库改进了。
* 新的Linux发行版发布了,有些已有的发行版试图重新设计它的整个声音软件栈,以改进用户体验。
* 人们读了我的上一篇文章,开始有了更多的认识,在某些方面,比以前更懂得开张圣听,察纳雅言。
* 我个人也更加深入地研究了这些问题,以便提供更详细的信息。

让我们拉近距离,观察一下OSS和ALSA现在的优势与不足。不是五年以前,不是去年,不是上个月,而是今天的它们。

首先,ALSA。
ALSA有三个组件组成。第一部分是内核中的驱动程序。提供了API,以便另外两部分与之通信。第二部分是给声音开发者的API,这允许开发人员创造与ALSA通信的程序。第三部分是混音组件,它可以放在另外两个组件之间,让多个使用ALSA API的程序同时输出声音。

为了便于理解,这里给出一幅图:

注意,图是我自己画的。我的艺术细胞很烂,我从来没有获过什么艺术奖。而且,这图也不是100%绝对准确的,但是已经足以让普通用户来了解其背后的大意了。

开发人员,想要在程序中输出声音,可以用以下任意一种方法:
* 通过ALSA API,直接输出到ALSA的内核API(当混音关闭时)
* 通过ALSA API,输出到“混音器”,混音器再输出到内核API(当混音关闭时)
* 用OSS v3的API直接输出到ALSA的内核API。
* 使用封装过的API,它们再利用上述3中方法输出。

可以看出,ALSA很灵活,具备OSSv3所不具备的混音功能,但是仍然为旧程序提供遗留的OSSv3支持。也允许关闭混音,以免某些情况下混音会造成声音质量下降,或者在某些时候引入用户所不希望的延迟。

两点很明确:ALSA提供可选的内核外的混音器,但ALSA的OSS遗留API不具备混音器。

其劣势也很明显,ALSA当初设计的目的是为了在比传统的“声音服务器”更低的层次,以较直接的方法,解决混音问题,

ALSA的明显优势是自由、开源、有混音器、可以支持多块声卡(这些OSSv3都不具备)。而且ALSA包含在内核中,而且迎合了新老程序的需求。

ALSA另一个不太明显的劣势是,它只支持Linux、FreeBSD、Solaris、Mac OS X和Windows上都没有。同样,一般的开发人员也觉得ALSA的本地API太难用了,但这值得商榷。

现在,看看今天的OSS。OSS现在的最新版是4,它与OSSv3完全不同。
与OSSv3的闭源不同,OSSv4是开源的,以GPL、3条款BSD和CDDL协议发布。
十年前,OSS在内核之内;新的OSSv4被踢出内核以外。因此,普通用户难以尝试之。旧的OSSv3缺乏混音,不支持多声卡,OSSv4不再是这样了。很多讨论OSS,测试OSS,把OSS与ALSA比较的人,很不幸,用的是十年前的旧的OSS,因此,它们得出的结论都不是今天的现实。

这里有一幅OSSv4的图:

想要开发基于OSSv4的程序的开发人员应该按照以下某种方法做:
* 通过OSS API直接输出到内核,有混音
* 通过ALSA API输出到OSS API,有混音
* 通过封装库的API,间接利用上述某种方法

不像ALSA,当你用OSSv4的时候,最终用户总是能够得到混音。而且由于混音在内核内部,它不会引起像ALSA那么严重的延迟。

OSSv4提供了它自己的ALSA模拟层,但它非常糟糕,我还没有发现一个ALSA程序能够在OSS的ALSA模拟层上正常地跑。但是,这不是个大问题,正如我刚才所说,ALSA自身的声音开发API就可以输出到OSS,这就达到了ALSA与OSS的兼容。你可以在这个链接中获得更多信息:http://insanecoding.blogspot.com/2009/05/perfect-sound-with-oss-version-4.html

ALSA自身的库也能做到这一点。它的结构如下:

如你所见,它既能输出到OSS后端,又能输出到ALSA内核后端(下文还会继续讨论其他后端)。

由于基于OSS和ALSA程序都可以使用OSS或者ALSA内核后端,它们两者的差别也就很微小了(注意:我这里说的不是OSSv3),据我的研究和测试,它们的差别并不明显。

OSS总是提供混音;ALSA不是。
OSS的混音质量高于ALSA,因为OSS使用了更加精准的混音算法。
OSS的延迟小于ALSA,因为一切都在内核中运行。[译注:有人不同意这一点,认为延迟和缓冲区大小有关,而不是和程序运行于内核态、用户态有关。见本文开头的链接]
ALSA允许操作系统进入待机然后回复,然后原本正在播放的声音继续播放;OSS则不可以,要求应用程序重新开始播放。
OSS对于某些声卡来说是必须的,因为ALSA要么没有相应的驱动程序,要么质量很烂。
ALSA对于某些声卡来说是必须的,因为OSS要么没有相应的驱动程序,要么质量很烂。
ALSA被包含进Linux内核,很容易得到;OSS(v4)则没有。

现在,问题是,普通用户属于上述的哪一类呢?如果用户的声卡只能在其中一种系统上工作,很显然,他们就应该使用那个能够正常工作的。当然,用户也可以两者都试试,看看哪个工作得比另一个更好。

如果用户真的需要让他的程序在Linux待机、回复之后还能正常播放声音,那么,ALSA是(目前)唯一的选择。我个人不觉得这是个问题,我更怀疑到底有多少Linux用户使用“待机”功能。Linux的待机功能很不怎么样,因为总有一些乱七八糟的硬件,比如网卡和显卡,把事情弄得更糟糕。

如果用户不想惹麻烦,ALSA是很明显的选择,因为它就包含在Linux内核里面。所以,用户用最新的ALSA比用最新的OSS更简单。但是,处理这些情况,应该是Linux发行版的工作。对于最终用户,切换ALSA和OSS应该是无缝而透明的。之后继续讨论该话题。

我们还发现,涉及到混音时,如果要选择一个混音质量和延迟都更好的选项,那么只要上述种种问题仍然存在,OSS都是更好的选择。但是,混音质量仅仅在音量更大的情况下变得明显,或者一些极个别情况下。而延迟问题仅仅在玩大型游戏的时候才明显,听音乐,看电影的时候都不是问题。

等等,以上都是后端的问题。应用程序开发人员的API问题怎么样?

很多人都喜欢对各个API指指点点(我也喜欢,尤其是在我的上一篇文章中)。但是它们真的没有抓住本质。首先,下图是一般的声音封装API的结构图:

应用程序利用封装器——如OpenAL、SDL或libao——进行输出,然后,声音传到高层或低层的后端,而用户不用关心这一细节。

由于后端因操作系统声音接口而异,封装器允许用户编写一个程序,在Windows、Mac OS X、Linux上都能运行,而且更简单。

Adobe的人说这是一种问题(见 http://blogs.adobe.com/penguin.swf/2007/05/welcome_to_the_jungle.html ),使得在Linux下无法输出声音。没有比这种言论更远离事实的了。这种图(见以上连接)很误导人。OpenAL、SDL、libao、GStreamer、NAS、Allegro很多也都在Windows下出现,但我却从来没听说有人抱怨。

我也可以画一个类似的Windows下的图:

上图也是不完整的。还有XAudio和其他封装器,还有一些Windows特有的封装器,我只是忘了名字而已。

这也完全没有给任何人惹来麻烦,也不应该是个问题。

对于使用而言,库有如下几种:
OpenAL – 强大,难用,擅长“3D音频”。我参考了一些示例,只用了一两个小时,就做了很多事情,给我的程序加上了声音。
SDL – 简单,使用回调API,如果这种风格恰好和你的程序的风格是一致的,那么这是个不错的选择。我个人用了半小时就能给我的程序加入声音,但我不觉得这满足所有人的需求。
libao – 非常简单,难以置信地容易使用,但是,如果你的程序是非阻塞的,这就是个问题了。我只用了几分钟,就给我的程序加入了很多音响效果。我只是觉得,如果你的程序需要给声音单独创造一个线程,这有时候就有点烦了。同样,看你的需求。

我还没有尝试其他封装器,所以我不能评论它们,但是,同样的理念在每个里面都有体现。

当然,在Linux平台下有真正的OSS和ALSAAPI。那么既然还有更可移植、更易用的封装库,为什么还会有人去直接使用OSS和ALSA呢?这一般都是对的,没有理由直接使用OSS和ALSAAPI来输出声音。某些情况下,使用封装API会引起额外延迟,你可能不期望。或者你并不需要封装的API提供的更多高级功能。

下面是对OSS和ALSA API的总结:
OSSv3 – 易用,很多开发者都喜欢它,存在于各种UNIX,除了Mac OS X以外。我只用了10分钟就给我的程序加入了声音。
OSSv4 – 基本上和v3兼容,甚至更易用,存在于除了Mac OS X以外的任何UNIX上,在Linux上使用ALSA后端,具备重新采样功能,还有内置AC3解码器,我做了几个声音程序,每个也只要10分钟。
ALSA -难以使用,我所问过的大多数程序员都不喜欢它,文档烂,除了Linux以外哪里都没有它。但是有些程序员喜欢它,他们觉得ALSA提供了比OSSAPI更高的灵活性。我个人花了3个小时才找到文档的头绪,并把声音加到程序中。然后,我发现声音只在我开发用的机器上可以工作,我又花了一个小时,看文档,改代码,才让程序在两台机器上都能工作。最后,我发布了我的程序,又发现一些人抱怨我的程序在他们的机器上没有声音,又收到了几个别的开发人员发给我的补丁。每个补丁都能让我的程序在他的机器上工作,但又让程序在我的某台机器无法工作。现在,一年已经过去了,我们的程序,在浪费了好多程序员好多个小时之后,终于可以在所有的机器上工作了。不过,我真的不信任它。我们作为开发人员,不应该忙于这种问题。当然,你可以反对我,甚至引用例子说你是怎么找到文档,快速实现声音,然后在所有的机器上经所有人测试都能够无瑕地工作。我也许只是太笨了。

我本以为OSS与ALSA之争是最终用户的事,也就是它们被迫使用某种框架。现在我知道,这与开发人员也息息相关。现在,主要问题很困难:如果我要利用OSSv4所提供的所有的额外特性,我就必须使用OSS后端。而用户则根本不关心到底用哪个,除非它们使用能够利用这些特性的某些程序。

对于封装的API,我也用几个程序得到了一些有意思的结果:
App -> libao -> OSS API -> OSS Back-end – Good sound, low latency.
App -> libao -> OSS API -> ALSA Back-end – Good sound, minor latency.
App -> libao -> ALSA API -> OSS Back-end – Good sound, low latency.
App -> libao -> ALSA API -> ALSA Back-end – Bad sound, horrible latency.
App -> SDL -> OSS API -> OSS Back-end – Good sound, really low latency.
App -> SDL -> OSS API -> ALSA Back-end – Good sound, minor latency.
App -> SDL -> ALSA API -> OSS Back-end – Good sound, low latency.
App -> SDL -> ALSA API -> ALSA Back-end – Good sound, minor latency.
App -> OpenAL -> OSS API -> OSS Back-end – Great sound, really low latency.
App -> OpenAL -> OSS API -> ALSA Back-end – Adequate sound, bad latency.
App -> OpenAL -> ALSA API -> OSS Back-end – Bad sound, bad latency.
App -> OpenAL -> ALSA API -> ALSA Back-end – Adequate sound, bad latency.
App -> OSS API -> OSS Back-end – Great sound, really low latency.
App -> OSS API -> ALSA Back-end – Good sound, minor latency.
App -> ALSA API -> OSS Back-end – Great sound, low latency.
App -> ALSA API -> ALSA Back-end – Good sound, bad latency.

如果你觉得看懂上表很难,这里是总结:
* OSS后端总是产生高质量的声音,除了通过OpenAL->ALSA输出到OSS以外。
* ALSA使用OSS API,声音质量一般更好,而且延迟也更低(一般是因为它避免了所有的混音)
* 要获得更好的声音,用OSS相关技术都更好。

等等。“声音服务器”应该处于什么位置呢?

“声音服务器”最初创造的时候是为了解决OSSv3的混音问题。当代的声音服务器栈看上去是这样:

很显然,这些“声音服务器”什么也不干,纯粹增加延迟,应该完全扔掉。KDE4不再使用aRts声音服务器了,而是使用一个封装API,称为Phonon,它可以处理很多种后端(而其中某些后端也可以输出到声音服务器)。

但是,如上所述,ALSA的混音质量不如OSS高。而且ALSA缺乏一些很好的功能,比如可以为每个不同的应用程序设置对应的音量控制。

现在,你可以关掉ALSA低质量的混音器,而是让应用程序在输出声音之前,在内部通过改变声波,完成音量控制,但是这对开发人员来说不是很友好。

为此,Fedora和Ubuntu都引入了一个所谓的“最先进的”声音服务器,称为PulseAudio。

如果你还记得这幅图:

可以看出,ALSA的API也可以输出到PulseAudio。这就意味着,用ALSA的API写的程序可以输出到PulseAudio,并可以无缝地使用PulseAudio的高质量混音器,而不用修改原有程序。PulseAudio也可以通过网络把声音发送到另一个远端的PulseAudio服务器上。PulseAudio的栈看上去是这样:

可以看出,它非常复杂。而100%精确描述PulseAudio的细节的图将更复杂。

由于PulseAudio是如此的先进,绝大多数的封装API都能输出到PulseAudio。Fedora和Ubuntu也预装且为最终用户将其配置好了。在某些情况下,它也可以接受为其他声音服务器书写的声音,如ESD,而不必在其上运行真正的ESD。这也就意味着,现在的很多程序发出的声音,在到达声卡之前,要经过很多很多层次。

有人认为,PulseAudio是我们新的救世主,为任何API书写的声音都可以输出到它上面,而且混音质量很好很强大。

例外的是,很多游戏玩家都抱怨PulseAudio增加了“奇大无比”的延迟,对于一些高端游戏来说,非常明显。用户不愿意在看到敌人和谐靠大家之后足足3秒钟才听到和谐靠大家声。别听别人胡扯,声音服务器根本没用,尤其是在这么肥硕和复杂的结构下还想为游戏提供可以接受的低延迟。

与PulseAudio的龌龊相比,看看这个:

请你考虑考虑混音、逐程序音量控制、应用程序兼容性和其他特性,你觉得哪个声音栈更好?

没错,不要忘记应用程序。经常有人告诉我说它们的程序是为某个特定的API写的,因此他们要么用ALSA后端,要么用OSS后端。但是,正如我上文所述,任何一个API都可以输出到另一个后端上去,而它本身可以什么也不做。如果设置正确(见 http://insanecoding.blogspot.com/2009/05/perfect-sound-with-oss-version-4.html ),你就算用新版的OSS播放Flash,也不会听不到声音。

那么,我们现在的情况是怎么样的呢?
最大的问题就是,我发现发行版根本就不考虑要不要让用户的选择更容易。Debian和基于它的发行版提供一个“Linux sound base”包,允许用户选择使用OSS后端还是ALSA后端,而它本身什么也不做。以下是这样的软件包应该提供的功能:
* 当用户选择OSS时,它应该安装最新的OSS包,也要安装ALSA的“ALSA API -> OSS后端”的接口,并自动设置正确。
* 尽量少地配置一个安装好的OpenAL库,让它使用OSS后端,最好SDL、libao和其他封装库也这样配置
* 安装新应用程序或者封装库的时候,根据以上设置,配置它们,让它们也用OSS。
* 如果用户选择ALSA,则类似地配置,只不过反过来。

这样的设置将允许用户很容易地选择这两个后端。如果用户的声卡在发行版默认配置的后端上无法工作,这会很有用。如果用户关心,这也将允许用户客观地测试哪个后端更好,而使用他们认为好的那一个。用户应该获得这样的权利。我个人认为OSS更好,但是,如果用户不喜欢默认的后端,我们应该允许用户选择。

我现在不断听到有人说:“但是,但是,OSS已经被踢出内核了,它也许再也不会被合并进来。”

让我们客观地分析这个问题。它有没有被包含进内核,真的很重要吗?就算KVM是内核的一部分,而VirtualBox不是,我们不是照样可以使用VirtualBox吗?就算KDE和GNOME都不是内核的一部分,我们不也可以使用它们吗?

最后,真正重要的是发行版的支持,而不是到底谁是内置的。谁关心内置不内置呢?唯一的区别在于,内核的开发人员不会去关心不包含在内核里的东西。但是这正是各大发行版正在做的工作,保证内核模块和相关的软件包在每个新的内核发布之后可以正常使用。

不管怎么样,总结几点:

我相信OSS比ALSA好,你倒是不见得同意。最好OSS和ALSA能够共享它们的驱动程序,而不是只支持某些声卡而不是另一些。

OSS应该支持系统挂起,以及其他比不过ALSA的特性,即使这些特性微不足道。这里有个建议:为什么Ubuntu雇用OSS的作者,并让它把最终用户最近遇到的一些问题弄得更友好一些呢?他现在正在找工作呢。(见 http://4front-tech.com/hannublog/?p=23 )然后再指派一些人改进现有的音量控制,让它对新的OSSv4更加友好,或者让HAL之类的东西默认就认识OSSv4。

问题应该直截了当地解决,而不是想PulseAudio那样绕弯,这个垃圾真该扔掉。如果用户真的需要远程音频,他应该很容易地把/dev/dsp映射到NFS文件系统中,然后用这种方法输出到OSS。网络透明性应该在文件系统级别完成,这就是UNIX的设计理念(即:一切都是文件),而不是让那些非UNIX的技巧在今天占领声音领域。

发行版们真的应该联合起来。虽然最近Draco Linux(见 http://www.dracolinux.org/ )出现了,且只包含OSS的发行版;而Arch Linux( http://www.archlinux.org/ )似乎把OSSv4视为头等公民,展示给用户,给用户选择,但是我已经告诉了它们,它们的ALSA兼容性部门没有给最终用户设置正确,这不好。而Arch Linux要求用户修改每个应用程序/库的配置文件。

由于OSS的操作系统抽象层,它的可移植性很好,与整个UNIX世界更加相关,而不像ALSA。FreeBSD则是采取自己的措施避免了OSS的抽象层,但还是基本上兼容的。如果愿意,用户可以在FreeBSD上安装官方版的OSSv4。

最后,Linux上的声音真的不需要那么可悲。发行版只要联合起来,阻止那些蔓延的指手画脚、宣传和“惧惑疑”论调,这些论调不是离题万里,就是根本错误。让我们不要被Adobe公司、PulseAudio宣传机器以及其他人或组织冲昏了头脑。让我们客观一点,让我们应用最好的解决方案,不要以庸人自居,也不要以五十步笑百步。

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: