Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1637843
  • 博文数量: 311
  • 博客积分: 7778
  • 博客等级: 少将
  • 技术积分: 4186
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 19:59
个人简介

蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88

文章存档

2012年(3)

2011年(115)

2010年(170)

2009年(23)

分类: 嵌入式

2011-02-21 17:45:50

Andrew Huang 转载请注明作者和网址.

   一般嵌入式系统只一个声音硬件作输出,所以大部分操作都采用默认的声卡即可操作。因此没有注意多网卡切换的问题,但是引入USB 声卡后,在嵌入式系统形成N个声卡,这样如果自动选定的缺省声卡,如何在应用程序切换声卡变成很现实的问题。
   因为设计关系统OSS是无法进行多声卡的操作,只有ALSA才支持.

   这个文章对于多声卡的操作描述很详细 

   对于ALSA多声卡操作我重点关注如下几个问题.
   1.如何象LINUX的图形界面显示系统的所有声卡的列表?
   2.如何选定某一个声卡为缺省输出?
   3.如果在应用程序选定某一个非缺省的声卡来播放声音?
  
   查看alsa声卡列表的功能,可以查看aplay -l 的实现.这个命令就是用来实现

一.测试环境

测试环境:mini6410 , Linux 2.6.28.6. 内核增加use auido  

1.1.编译内核
  增加USB Audio选项
   
1.2 编译 alsa-lib/alsa-utils
 
编译alsa库最好编译两次:
  
第一次把alsa的配置文件放入output目录以便发布.
./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared  --disable-python   --with-plugindir=/usr/local/lib/alsa_lib

如果是mini6410则需要把缺省的设备结点目录/dev/snd 改成 /dev

./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared  --disable-python   --with-plugindir=/usr/local/lib/alsa_lib --with-alsa-devdir=/dev

make 
make install

第二次让缺省库使用时去找/usr/local/share/alsa,

make clean

   ./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared  --disable-python  --with-configdir=/usr/local/share/alsa  --datarootdir=$PWD/../../output/arm-linux/share 
--with-alsa-devdir=/dev #红色是mini6410要加的
make 
make install
这一次为解决运行时提示配置文件

ALSA lib pcm.c:2145:(snd_pcm_open_noupdate) Unknown PCM default

aplay: main:546: audio open error: No such file or directory


编译alsa-utils 进行测试


./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared    --with-configdir=/usr/local/share --with-libiconv-prefix=$PWD/../../output/arm-linux CFLAGS="-I$PWD/../../output/arm-linux/include" LDFLAGS="-L$PWD/../../output/arm-linux/lib -lasound -liconv"  --disable-alsamixer --disable-xmlto


1.3 拷贝alsa配置文件到在开发板

   在开发板上创建
   mkdir -p  /usr/local/share/alsa/

  cp -rfa $PWD/../../output/arm-linux/share/alsa/* /usr/local/share/alsa

运行aplay -l 会有如下结果,可以看到AC97和USB 声卡

[root@FriendlyARM bin]# ./run.sh
/mnt/nfs/obt9808_sw/output/arm-linux/lib
**** List of PLAYBACK Hardware Devices ****
card 0: SMDK6400 [SMDK6400], device 0: AC97 HiFi AC97 HiFi-AC97-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: U0x4b40x307 [USB Device 0x4b4:0x307], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

二.应用程序多声卡操作

alsa-utils 测试

2.1 播放测试:

测试音源,可以从如下网址下载wav文件进行测试
    
这里有一些标准的电话铃声下载


以下是用默认声卡.
   export LD_LIBRARY_PATH=/mnt/nfs/output/arm-linux/lib;./aplay ringback.wav

指定第二块声卡播放,用-D参数,设备名来自-l的查询

方法1:用名字指定
 export LD_LIBRARY_PATH=/mnt/nfs/obt9808_sw/output/arm-li
nux/lib;./aplay  east123.wav  -D default:CARD=U0x4b40x307

方法2:用声卡编号指定:
  
export LD_LIBRARY_PATH=/mnt/nfs/obt9808_sw/output/arm-linux/lib;./aplay  east123.wav  -D plughw:1,0
第一个声卡是 
plughw:0,0

录音使用arecord
  arecord -D default:CARD=U0x4b40x307 -d 20 -c 2 -t wav -r 8000 -f "Signed 16 bit Little Endian" 4.wav
  
rec -d default:CARD=U0x4b40x307 -c 2 -r 8000 -t wav -s w 8.wav

madplay测试

./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --with-alsa --with-libiconv-prefix=$PWD/../../output/arm-linux --enable-shared --enable-static CPPFLAGS="-I$PWD/../../output/arm-linux/include" LDFLAGS="-L$PWD/../../output/arm-linux/lib -lasound " --with-libiconv-prefix="$PWD/../../output/arm-linux/"

增加多声卡支持

分析其代码,在alsa下有专门的处理init初始化代码。这里打开音频设备中,虽然有init->path,但是在alsa总是初始化为空,因此alsa总是打开缺省设备用。



static
int init(struct audio_init *init)
{
    int err;

    if (init->path)
        err = snd_pcm_open(&alsa_handle, init->path, SND_PCM_STREAM_PLAYBACK, 0);
    else
        err = snd_pcm_open(&alsa_handle, defaultdev, SND_PCM_STREAM_PLAYBACK, 0);

    if (err < 0) {
        audio_error=snd_strerror(err);
        return -1;
    }

    return 0;
}


模仿 audio_sun.c 增加一个用环境变量来修改声卡的的名字,红色声卡是



static
int init(struct audio_init *init)
{
    int err;
    
    if (init->path == 0) //add by Andrew Huang
    init->path = getenv("AUDIODEV");

   
  printf("hxy %s:init->path %s\n",__FUNCTION__,init->path);

    if (init->path)
        err = snd_pcm_open(&alsa_handle, init->path, SND_PCM_STREAM_PLAYBACK, 0);
    else
        err = snd_pcm_open(&alsa_handle, defaultdev, SND_PCM_STREAM_PLAYBACK, 0);

    if (err < 0) {
        audio_error=snd_strerror(err);
        return -1;
    }

    return 0;
}


测试结果,可以从第二块声卡播放出来

 export AUDIODEV=plughw:1,0;export LD_LIBRARY_PATH=/mnt/n
fs/obt9808_sw/output/arm-linux/lib;./madplay 1.mp3

mplayer 的测试
mplayer运行时指定声卡的参数,可以参考这几篇文章

oss模式测试
 
./configure --prefix=$PWD/../../output/arm-linux --cc=arm-linux-gcc  --ar=arm-linux-ar  \
 --ranlib=arm-linux-ranlib --disable-gui   --disable-alsa  \
--target=arm-armv4-linux --host-cc=gcc  --disable-freetype\
 --enable-fbdev --disable-mencoder --disable-sdl --disable-live  --disable-dvdread \
 --disable-libdvdcss-internal --disable-x11 --enable-cross-compile  --disable-mp3lib \
  --enable-mad  --with-extraincdir="$PWD/../../output/arm-linux/include  "  --with-extralibdir="$PWD/../../output/arm-linux/lib " \
  --disable-dvdnav  --disable-dvdread-internal    --disable-jpeg --disable-tga \
 --disable-dvbhead --disable-pnm --disable-tv --disable-ivtv \
 --disable-fontconfig --disable-xanim --disable-win32dll --disable-armv5te --disable-armv6

以下是测试成功的oss指令
 
export LD_LIBRARY_PATH=/mnt/nfs/obt9808_sw/output/arm-l
inux/lib; ./mplayer  -vo null -ac mad -ao oss:/dev/dsp1 1.mp3

alsa模式:

以下是生成mplayer的Makefile,注意打开alsa,并且要关掉oss,否则会指定失败.
 
./configure --prefix=$PWD/../../output/arm-linux --cc=arm-linux-gcc  --ar=arm-linux-ar   --ranlib=arm-linux-ranlib --disable-gui   --enable-alsa  --disable-ossaudio --target=arm-armv4-linux --host-cc=gcc  --disable-freetype --enable-fbdev --disable-mencoder --disable-sdl --disable-live  --disable-dvdread  --disable-libdvdcss-internal --disable-x11 --enable-cross-compile  --disable-mp3lib   --enable-mad  --with-extraincdir="$PWD/../../output/arm-linux/include  "  --with-extralibdir="$PWD/../../output/arm-linux/lib "   --disable-dvdnav  --disable-dvdread-internal    --disable-jpeg --disable-tga  --disable-dvbhead --disable-pnm --disable-tv --disable-ivtv  --disable-fontconfig --disable-xanim --disable-win32dll --disable-armv5te --disable-armv6

测试成功alsa指令:

  
 export LD_LIBRARY_PATH=/mnt/nfs/obt9808_sw/output/arm-l
inux/lib; ./mplayer  -vo null  -ao alsa:noblock:device=plughw=1,0 1.mp3

但还有一个更简单方法是也是修改mplayer插件的目录的libmad库源码来象madplay一样播放多声卡声音
  

SDL的音乐库的测试

 sdl主要用SDL_mix来播放音乐.它也依赖SDL库,因此要求SDL支持多声卡支持.
  必须注意两点: 1.SDL必须打开alsa支持
               2. SDL_mixer必须使用libmad库,这样可以用AUDIODEV环境变量指定.

SDL的生成脚本:
   ./configure --prefix=$PWD/../../output/arm-linux --disable-video-nanox --disable-video-qtopia --disable-video-photon  --disable-video-ggi --disable-video-svga --disable-video-aalib --disable-video-dummy --disable-video-dga --disable-arts --disable-esd --enable-alsa --disable-video-x11 --disable-nasm    --enable-joystick --enable-input-tslib --enable-video-fbcon --host=arm-linux --build=i386 CPPFLAGS="-I$PWD/../../output/arm-linux/include"   LDFLAGS="-L$PWD/../../output/arm-linux/lib -lts -liconv" --with-alsa-prefix=$PWD/../../output/arm-linux

SDL_mixer的生成脚本:
  
./configure --enable-music-mp3-mad-gpl --enable-music-mp3=no --host=arm-linux --prefix=$PWD/../../output/arm-linux --with-sdl-prefix=$PWD/../../output/arm-linux --enable-shared --enable-static

测试,编译SDL_mixer自带的测试程序playmus.c 可以从第二个声卡来听到音乐声音

以下是成功运行LINUX脚本:

export PRJ_DIR=/mnt/nfs/obt9808_sw/output/arm-linux
export LD_LIBRARY_PATH=${PRJ_DIR}/lib
export AUDIODEV=plughw:1,0
#export AUDIODEV=default:CARD=U0x4b40x307
./playmus 1.mp3




阅读(6278) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~