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

全部博文(174)

文章存档

2011年(1)

2010年(24)

2009年(149)

我的朋友

分类: LINUX

2009-04-08 23:42:33

这是一个简单的播放声音的示例:
(由于项目只是需要简单的驱动,过多的专研这里就不做了,只是照着例子来看一些非常基本的。)
只要看PCM Interface的一些部分就可以了。

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
      
int main(int argc, char *argv[])
{
    int i;
    int err;
    int rate = 44100;
    short buf[128];
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;

    if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        fprintf (stderr, "cannot open audio device %s (%s)\n",
             argv[1],
             snd_strerror (err));
        exit (1);
    }
     
    if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
        fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
             snd_strerror (err));
        exit (1);
    }
             
    if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
        fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        fprintf (stderr, "cannot set access type (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
        fprintf (stderr, "cannot set sample format (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, 0)) < 0) {
        fprintf (stderr, "cannot set sample rate (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
        fprintf (stderr, "cannot set channel count (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
        fprintf (stderr, "cannot set parameters (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    snd_pcm_hw_params_free (hw_params);

    if ((err = snd_pcm_prepare (playback_handle)) < 0) {
        fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    for (i = 0; i < 100000; ++i) {
        if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) {
            fprintf (stderr, "write to audio interface failed (%s)\n",
                 snd_strerror (err));
            exit (1);
        }
    }

    snd_pcm_close (playback_handle);
    exit (0);
}


在线文档的摘录:

打开一个snd_pcm设备:


int snd_pcm_open
( ** pcmp,
const char * name,
 stream,
int mode 
)

Opens a PCM.

Parameters:
pcmp Returned PCM handle
name ASCII identifier of the PCM handle
stream Wanted stream
mode Open mode (see , )
Returns:
0 on success otherwise a negative error code

相应的类型:
typedef struct _snd_pcm

PCM handle 设备句柄

typedef enum

PCM stream (direction) 指的是PCM数据流的流向

Enumerator:
SND_PCM_STREAM_PLAYBACK  Playback stream 播放
SND_PCM_STREAM_CAPTURE  Capture stream 捕捉


设备参数实例化:

snd_pcm_hw_params_malloc (&hw_params)

The ALSA PCM device uses two groups of PCM related parameters. The hardware parameters contains the stream description like format, rate, count of channels, ring buffer size etc. The software parameters contains the software (driver) related parameters...

typedef struct _snd_pcm_hw_params

PCM hardware configuration space container  硬件配置参数


初始化设备参数:

int snd_pcm_hw_params_any



Fill params with a full configuration space for a PCM.

Parameters:

pcm PCM handle
params Configuration space 
注意到,如果单纯是设置硬件参数,不应该需要设备的句柄,可能是设备参数会根据设备的信息来设置。之后程序设置和应用相关的选项。包括:
access model
format
rate
channel
...

读写缓冲区的模式:

snd_pcm_hw_params_set_access 


ALSA knows about five access modes. The first three can be used for direct communication. ...(关于前面三个选项略,我觉得是设置和其他程序通信的,名字中有MMAP,就是内存映射,应该只要关心后面2个,而且应该大都数都是INTERLEAVED的,所以没必要考虑太多。)The last two access modes describes the read / write access methods. The access represents the read / write interleaved access and the represents the non-interleaved access.


PCM样本的格式(有/无符号,bit位数,大/小端):

snd_pcm_hw_params_set_format

typedef enum

PCM sample format 

参数列表就不给出了,libmad输出的应该是SND_PCM_FORMAT_S16_LE?


采样率:

snd_pcm_hw_params_set_rate_near

不使用..._set_rate的原因不是很清楚,但是这个函数的功能很明显。

int snd_pcm_hw_params_set_rate_near ( pcm,
params,
unsigned int *  val,
int *  dir  
)

Restrict a configuration space to have rate nearest to a target.

Parameters:
pcm  PCM handle
params  Configuration space
val  approximate target rate / returned approximate set rate
dir  Sub unit direction (不是很理解?)
Returns:
0 otherwise a negative error code if configuration space is empty
target/chosen exact value is <,=,> val following dir (-1,0,1)
(不是很理解?) 


设置声道数:

int snd_pcm_hw_params_set_channels (pcm,
params,
unsigned int val 
)

Restrict a configuration space to contain only one channels count.

Parameters:
pcm  PCM handle
params  Configuration space
val  channels count
Returns:
0 otherwise a negative error code if configuration space would become empty 

设置设备的参数:

snd_pcm_hw_params


释放设备参数句柄:

snd_pcm_hw_params_free


准备使用PCM设备:

nd_pcm_prepare


写入PCM设备,交叉模式(如果是捕捉,就应该是读出;access model应该与此有关)


snd_pcm_sframes_t snd_pcm_writei ( snd_pcm_t * pcm,
  const void * buffer,
  snd_pcm_uframes_t size
 )

Write interleaved frames to a PCM.


Parameters:
 pcm PCM handle
 buffer frames containing buffer
 size frames to be written

Returns:
a positive number of frames actually written otherwise a negative error code
Return values:
 -EBADFD PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)
 -EPIPE an underrun occurred
 -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)

If the blocking behaviour is selected, then routine waits until all requested bytes are played or put to the playback ring buffer. The count of bytes can be less only if a signal or underrun occurred.
If the non-blocking behaviour is selected, then routine doesn


关闭PCM设备:

snd_pcm_close

阅读(3164) | 评论(0) | 转发(0) |
0

上一篇:声卡设备

下一篇:ARM程序设计

给主人留下些什么吧!~~