2009年1月10日星期六

alsa-oss

很多老程序都是用 OSS 做声音驱动的(如 mp3blaster),ALSA 为这些程序提供了一种解决方案,这就是 alsa-oss
/usr/lib/libalsatoss.a
/usr/lib/libalsatoss.so.0.0.0
/usr/lib/libossredir.la
/usr/lib/libaoss.a
/usr/lib/libossredir.a
/usr/lib/libaoss.la
/usr/lib/libalsatoss.la
/usr/lib/libaoss.so.0.0.0
/usr/bin/aoss
/usr/share/lintian/overrides/alsa-oss
/usr/share/man/man1/aoss.1.gz
/usr/share/doc/alsa-oss/copyright
/usr/share/doc/alsa-oss/changelog.gz
/usr/share/doc/alsa-oss/changelog.Debian.gz
/usr/include/oss-redir.h
/usr/lib/libalsatoss.so
/usr/lib/libaoss.so
/usr/lib/libaoss.so.0
/usr/lib/libalsatoss.so.0
可以看出来,这里提供了一个命令而已,那么是怎么实现的呢?可以很容易发现 aoss 本质上只是一个 bash script,其内容如下:
#!/bin/sh

# A simple script to facilitate the use of the OSS compatibility library.
# Usage:
# aoss

if [ -d /proc/asound ]; then
prefix=/usr
exec_prefix=${prefix}
LD_PRELOAD=${exec_prefix}/\$LIB/libaoss.so${LD_PRELOAD:+:$LD_PRELOAD} exec "$@"
else
exec "$@"
fi
exit 1
可以看出来在存在 /proc/asound 时(有 ALSA 驱动),该 script 就会在程序执行前提前载入 libaoss.so,这个动态链接库将把调用 OSS 发声程序需要的函数用 ALSA 实现。这是一个非常有意思的技术,也正因为如此,才使得制作 OSS 的 wrapper 成为可能。比如执行 mp3blaster,就可以直接 aoss mp3blaster 了。

esound

Linux 世界里面总是存在着千奇百怪的产品,ESD 算是一个了吧。早期让 Linux 用声音简直是痛苦极了,现在有了 ALSA,还是好了很多,一些遗留下来的工具还在发挥着余热。

ESD 简单说就是一个混音器,但是它允许用户从网络上进行访问(network transparent),这意味着你可以在一台机器上打开播放器,另外一台机器的喇叭响了。这也是采用了 CS 构架的原因。之后有很多类似的项目用来取代 ESD,有的已经停止了开发比如 aRtsD,有的尚还在开发(RoarAudio)或者已经比较完整(如 JACK Audio Connection Kit、NAS 和 PurseAudio),有的和 ESD 类似也是 network transparent,有的不是。

debian 里面服务器在 esound 里面,
/usr/bin/esd
/usr/share/man/man1
/usr/share/man/man1/esd.1.gz
/usr/share/doc/esound
客户端在 esound-clients 里面
/usr/share/man/man1/esddsp.1.gz
/usr/share/man/man1/esdfilt.1.gz
/usr/share/man/man1/esdloop.1.gz
/usr/share/man/man1/esdmon.1.gz
/usr/share/man/man1/esdplay.1.gz
/usr/share/man/man1/esdrec.1.gz
/usr/share/man/man1/esdcat.1.gz
/usr/share/man/man1/esdctl.1.gz
/usr/share/man/man1/esdsample.1.gz
/usr/lib/esound/libesddsp.so.0.2.39
/usr/lib/mime/packages/esound-clients
/usr/bin/esdcat
/usr/bin/esdctl
/usr/bin/esddsp
/usr/bin/esdfilt
/usr/bin/esdloop
/usr/bin/esdmon
/usr/bin/esdplay
/usr/bin/esdrec
/usr/bin/esdsample
/usr/share/doc/esound-clients
/usr/lib/esound/libesddsp.so.0
另外一部分在 esound-common 里面,
/etc/esound/esd.conf
/usr/share/doc/esound-common/TIPS
/usr/share/doc/esound-common/TODO
/usr/share/doc/esound-common/html
/usr/share/doc/esound-common/html/x66.html
/usr/share/doc/esound-common/html/r311.html
/usr/share/doc/esound-common/html/r313.html
/usr/share/doc/esound-common/html/x296.html
/usr/share/doc/esound-common/html/x299.html
/usr/share/doc/esound-common/html/x179.html
/usr/share/doc/esound-common/html/x241.html
/usr/share/doc/esound-common/html/x302.html
/usr/share/doc/esound-common/html/index.html
/usr/share/doc/esound-common/html/x305.html
/usr/share/doc/esound-common/html/x119.html
/usr/share/doc/esound-common/html/c250.html
/usr/share/doc/esound-common/html/x308.html
/usr/share/doc/esound-common/html/x26.html
/usr/share/doc/esound-common/html/c76.html
/usr/share/doc/esound-common/html/x259.html
/usr/share/doc/esound-common/html/x265.html
/usr/share/doc/esound-common/html/c19.html
/usr/share/doc/esound-common/html/x268.html
/usr/share/doc/esound-common/html/c271.html
/usr/share/doc/esound-common/html/x47.html
/usr/share/doc/esound-common/html/a346.html
/usr/share/doc/esound-common/html/x277.html
/usr/share/doc/esound-common/html/x211.html
/usr/share/doc/esound-common/html/c32.html
/usr/share/doc/esound-common/html/x281.html
/usr/share/doc/esound-common/html/c285.html
/usr/share/doc/esound-common/html/c290.html
/usr/share/doc/esound-common/README
/usr/share/doc/esound-common/NEWS.gz
/usr/share/doc/esound-common/README.Debian
/usr/share/doc/esound-common/AUTHORS
/usr/share/doc/esound-common/copyright
/usr/share/doc/esound-common/changelog.gz
/usr/share/doc/esound-common/changelog.Debian.gz
/usr/share/doc-base/esound
其实使用 ESD 很简单,一般或者有某些程序的 module 支持 ESD 输出,可以通过命令行参数 -s server:port 指定或者设定 ESPEAKER 环境变量。

配置文件 /etc/esound/esd.conf 就是 ESD 的 daemon 启动的配置文件了,esd 参数不多,主要就是选择链接类型(-unix 还是 -tcp),指定端口 -port(默认是 5001),指定设备(-d),是否打开时候 beep(-nobeeps)等。可惜必须用 root 启动该进程。

clients 里面提供给我们一些命令,如 esdctl 用来控制 esd 的状态,esdrec 从 server 录下来一段,然后可以用 esdcat 发送给 ESD 播放,esdplay 相当于把一个已有的声音文件如 wav 从 ESD 播放,esdsample 允许播放的时候重采样,另外还有 esdloop 等不是很清楚实际作用。

那么如何使得本地的 mic 可以直接把声音播放到远程主机呢?一种想法就是利用管道,使用 arecord 或者 rec 等程序进行录制,通过管道送给 esdplay。可是实验发现 esdplay 不支持管道...