Chinaunix首页 | 论坛 | 博客
  • 博客访问: 515708
  • 博文数量: 174
  • 博客积分: 8001
  • 博客等级: 中将
  • 技术积分: 1840
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-04 19:30
文章分类

全部博文(174)

文章存档

2011年(1)

2010年(24)

2009年(149)

我的朋友

分类: LINUX

2009-05-21 21:59:15

由于开发板是不支持ALSA的,它使用DAC3550的芯片,接在ssi端口。
PS:同步串行接口(SSI)是各类DSP处理器中的常见接口,这是因为编解码器(Coder/Decoder, CODEC)的数字接口即为SSI
所以用mad解码的方法也要改变为硬解码。主要的原因是,现在的情况是没有文档和源代码。只有关于这个驱动:ssiDAC3550A的源码。所以现在应该试着根据这个驱动来写一些应用程序。
虽然说,开发板上的不像是平常的声卡,但是应该认为他已经通过写了适当的驱动程序,而被系统识别,应该是作为声卡设备而存在的。交叉编译alsa应该没有问题才对。
引用:

其实我们的声卡驱动不管是alsa或者oss,这是两种接口,跟内核和硬件有些关系,而做应用层的小播放器,调用的
声卡的api函数区别不大,做些针对alsa的播放器,才需要好好了解,
我们很多时候只是操作/dev/dsp和/dev/mixer这两设备文件,alsa是高级些接口也是做了相应设备上连接的

做交叉播放器,还要把相应的常用的音视解码库交叉进去,这些这些库可以做动态的或者静态的库加载到你的播放器上
看你的板子频率怎么样,一般的arm都需要dsp,或者高率高效的软件才可以,测试过mp3在arm9上用纯软解码gstreamer库就可以
用mplay速度就不行,楼主如果只用很少的功能,就自己参考写点,如果基本要用到,还是着着开源的播放器交叉编译。

事实上呢,有了操作系统,应该就能提供较为统一的硬件视图。alsa的交叉编译估计不能,因为好像要有/dev/mixer,这个开发板上没有。
所以只是操作/dev/dsp,方向确定之后也好找资料了。
翻译:
(PS:这是来源于Linux Multymedia Guide的著作。是oreilly出版社于网上的一系列open books,有兴趣可以看看更多的开放书籍.)
只重点讲写入数据。
/dev/dsp 是数字采样和记录设备,也许对于多媒体应用程序而言,是最重要的设备。向该设备写入数据,访问D/A转换器,就能够产生声音。从该设备读取数据,访问A/D转换器,就能记录声音。
DSP的名字就代表着数字信号处理器。
某些声卡提供了不止一个数字采样设备,这样就会有/dev/dsp1。
同一时间只能有一个进程占用/dev/dsp,否则就会产生EBUSY错误。
访问/dev/dsp时:
1.如果读取太慢(低于采样率),就会抛弃超出的数据,产生空隙。如果太快,就会阻塞进程。
2.Writing a sequence of digital sample values to the DSP device produces sound output. This process is illustrated in (b). Again, the format can be defined using ioctl calls, but defaults to the values given above for the read system call (8-bit unsigned data, mono, 8 kHz sampling).
写入一系列数字采样就能产生声音。通过ioctl系统调用能够改变数据的格式。
If the data are written too slowly, there will be dropouts or pauses in the sound output. Writing the data faster than the sampling rate will simply cause the kernel sound driver to block the calling process until the sound card hardware is ready to process the new data. Unlike some devices, there is no support for non-blocking I/O.
如果写入太慢,声音数据就会有间断。如果写入太快,就会阻塞进程;不像一些设备,没有non-blocking I/O。

If you don't like the defaults, you can change them through ioctl calls. In general you should set the parameters after opening the device, and before any calls to read or write. You should also set the parameters in the order in which they are described below.

All DSP ioctl calls take a third argument that is a pointer to an integer. Don't try to pass a constant; you must use a variable. The call will return -1 if an error occurs, and set the global variable errno.

If the hardware doesn't support the exact value you call for, the sound driver will try to set the parameter to the closest allowable value. For example, with my sound card, selecting a sampling rate of 9000 Hz will result in an actual rate of 9009 Hz being used.

If a parameter is out of range, the driver will set it to the closest value (i.e., the upper or lower limit). For example, attempting to use 16-bit sampling with an 8-bit sound card will result in the driver selecting 8 bits, but no error will be returned. It is up to you, the programmer, to verify that the value returned is acceptable to your application.

All of the ioctl calls for the DSP device are names starting with SOUND_PCM. Calls in the form SOUND_PCM_READ_XXX are used to return just the current value of a parameter. To change the values, the ioctl calls are named like SOUND_PCM_WRITE_XXX. As discussed above, these calls also return the selected value, which is not necessarily the same as the value passed to the sound driver.

The ioctl constants are defined in the header file linux/soundcard.h. Let's examine each of them in detail.

你可以通过ioctl控制设备(这是当然的,任何能被系统识别的设备都必须提供这一个接口。要记住操作系统是有这方面的优势的。)如果你所设定的参数不适合,那么会自动选择最为接近的参数。如果超出了范围也会选择上限。不会返回错误。

使用SOUND_PCM_READ_XXX 来读取现在的设备参数。使用SOUND_PCM_WRITE_XXX来设置设备参数。下面介绍几个重要参数:

SOUND_PCM_WRITE_BITS

Sets the sample size, in bits. Valid choices are 8 and 16, but some cards do not support 16.

设置数据样本的位数,8或16位。

SOUND_PCM_READ_BITS

Returns the current sample size, which should be either 8 or 16 bits.

SOUND_PCM_WRITE_CHANNELS

Sets the number of channels--1 for mono, 2 for stereo. When running in stereo mode, the data is interleaved when read or written, in the format left-right-left-right.... Remember that some sound cards do not support stereo; check the actual number of channels returned in the argument.

设置声道。 

SOUND_PCM_READ_CHANNELS

Returns the current number of channels, either 1 or 2.

SOUND_PCM_WRITE_RATE

Sets the sampling rate in samples per second. Remember that all sound cards have a limit on the range; the driver will round the rate to the nearest speed supported by the hardware, returning the actual (rounded) rate in the argument. Typical lower limits are 4 kHz; upper limits are 13, 15, 22, or 44 kHz.

设置采样率。 

SOUND_PCM_READ_RATE

Returns just the current sampling rate. This is the rate used by the kernel, which may not be exactly the rate given in a previous call to SOUND_PCM_WRITE_RATE, because of the previously discussed rounding.

示例程序

/*
 * parrot.c
 * Program to illustrate /dev/dsp device
 * Records several seconds of sound, then echoes it back.
 * Runs until Control-C is pressed.
 */


#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>

#define LENGTH 3 /* how many seconds of speech to store */
#define RATE 8000 /* the sampling rate */
#define SIZE 8 /* sample size: 8 or 16 bits */
#define CHANNELS 1 /* 1 = mono 2 = stereo */

/* this buffer holds the digitized audio */
unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];

int main()
{
  int fd;    /* sound device file descriptor */
  int arg;    /* argument for ioctl calls */
  int status; /* return status of system calls */

  /* open sound device */
  fd = open("/dev/dsp", O_RDWR);
  if (fd < 0) {
    perror("open of /dev/dsp failed");
    exit(1);
  }

  /* set sampling parameters */
  arg = SIZE;     /* sample size */
  status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_BITS ioctl failed");
  if (arg != SIZE)
    perror("unable to set sample size");

  arg = CHANNELS; /* mono or stereo */
  status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  if (arg != CHANNELS)
    perror("unable to set number of channels");

  arg = RATE;     /* sampling rate */
  status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
  if (status == -1)
    perror("SOUND_PCM_WRITE_WRITE ioctl failed");

  while (1) { /* loop until Control-C */
    printf("Say something:\n");
    status = read(fd, buf, sizeof(buf)); /* record some sound */
    if (status != sizeof(buf))
      perror("read wrong number of bytes");
    printf("You said:\n");
    status = write(fd, buf, sizeof(buf)); /* play it back */
    if (status != sizeof(buf))
      perror("wrote wrong number of bytes");
    /* wait for playback to complete before recording again */
    status = ioctl(fd, SOUND_PCM_SYNC, 0);
  if (status == -1)
    perror("SOUND_PCM_SYNC ioctl failed");
  }
}

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