linux嵌入式应用开发- ubuntu eclipse/c ALSA音频编程

软件:ubuntu  eclipse gcc 版权所有:http://blog.csdn.net/sea918

1,音频开发模型:

OSS(open sound system)  linux/unix 平台的上早期的统一音频接口。linux kernl 2.6 版本以前

    其它提供两种设备文件以供编程。 常用的操作函数为open、close、read、write、ioctl.

(/dev/dsp录音设备文件/dev/audio播放设备文件)

ALSA(a)目前流行的编译框架。linux 2.6 版本发后支持。

提供统一的编程接口:snd_pcm_open、snd_pcm_close、snd_pcm_hw_params

基设备文件为:/dev/snd/pcmC0D0p/dev/snd/pcmC0D0c /dev/snd/pcmC0D1p/dev/snd/timer

可以通过bash命令查看 alsa 驱动版本:

root@ubuntu:cat  /proc/asound/version

Advanced linux Sound Architecture Driver Version 1.0.23


2,Alsa-lib 编译

a,下载并安装 alsa-lib库

  root@ubuntu: tar -xvf  alsa-lib-1.0.13.tar.bz2

root@ubuntu:./configure

root@ubuntu:make

root@ubuntu: make install

3,编程

a,添加头文件

#include <alsa/asoundlib.h>

b,编程录音代码.

/*

This program reads from the default PCM device
and writes to standard output for 5 seconds of data.

*/

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

#define LENGTH    3   //录音时间,秒
#define RATE    9600 //采样频率
#define SIZE    16   //量化位数
#define CHANNELS 1   //声道数目
#define RSIZE    8    //buf的大小,

/********以下是wave格式文件的文件头格式说明******/
/*------------------------------------------------
|             RIFF WAVE Chunk                  |
|             ID = 'RIFF'                     |
|             RiffType = 'WAVE'                |
------------------------------------------------
|             Format Chunk                     |
|             ID = 'fmt '                      |
------------------------------------------------
|             Fact Chunk(optional)             |
|             ID = 'fact'                      |
------------------------------------------------
|             Data Chunk                       |
|             ID = 'data'                      |
------------------------------------------------*/
/**********以上是wave文件格式头格式说明***********/
/*wave 文件一共有四个Chunk组成,其中第三个Chunk可以省略,每个Chunk有标示(ID),
大小(size,就是本Chunk的内容部分长度),内容三部分组成*/
struct fhead
{
/****RIFF WAVE CHUNK*/
unsigned char a[4];//四个字节存放'R','I','F','F'
long int b;        //整个文件的长度-8;每个Chunk的size字段,都是表示除了本Chunk的ID和SIZE字段外的长度;
unsigned char c[4];//四个字节存放'W','A','V','E'
/****RIFF WAVE CHUNK*/
/****Format CHUNK*/
unsigned char d[4];//四个字节存放'f','m','t',''
long int e;       //16后没有附加消息,18后有附加消息;一般为16,其他格式转来的话为18
short int f;       //编码方式,一般为0x0001;
short int g;       //声道数目,1单声道,2双声道;
long int h;        //采样频率;
long int i;        //每秒所需字节数;
short int j;       //每个采样需要多少字节,若声道是双,则两个一起考虑;
short int k;       //即量化位数
/****Format CHUNK*/
/***Data Chunk**/
   unsigned char p[4];//四个字节存放'd','a','t','a'
long int q;        //语音数据部分长度,不包括文件头的任何部分
}wavehead;//定义WAVE文件的文件头结构体


int startRecord(void)
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
int fd_f;
int status;



/*以下wave 文件头赋值*/
wavehead.a[0]='R';
wavehead.a[1]='I';
wavehead.a[2]='F';
wavehead.a[3]='F';
wavehead.b=LENGTH*RATE*CHANNELS*SIZE/8-8;
wavehead.c[0]='W';
wavehead.c[1]='A';
wavehead.c[2]='V';
wavehead.c[3]='E';
wavehead.d[0]='f';
wavehead.d[1]='m';
wavehead.d[2]='t';
wavehead.d[3]=' ';
wavehead.e=16;
wavehead.f=1;
wavehead.g=CHANNELS;
wavehead.h=RATE;
wavehead.i=RATE*CHANNELS*SIZE/8;
wavehead.j=CHANNELS*SIZE/8;
wavehead.k=SIZE;
wavehead.p[0]='d';
wavehead.p[1]='a';
wavehead.p[2]='t';
wavehead.p[3]='a';
wavehead.q=LENGTH*RATE*CHANNELS*SIZE/8;
/*以上wave 文件头赋值*/


/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default",
                    SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
    fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc));
    exit(1);
}

/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);

/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);

/* Set the desired hardware parameters. */

/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
                              SND_PCM_FORMAT_S16_LE);

/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, CHANNELS);

/* 44100 bits/second sampling rate (CD quality) */
val = RATE;
snd_pcm_hw_params_set_rate_near(handle, params,
                                  &val, &dir);

/* Set period size to 32 frames. */
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle,
                              params, &frames, &dir);

/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
    fprintf(stderr,
            "unable to set hw parameters: %s\n",
            snd_strerror(rc));
    exit(1);
}

/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params,
                                      &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);

/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params,
                                         &val, &dir);
loops = 5000000 / val;




if(( fd_f = open("./sound.wav", O_CREAT|O_RDWR,0777))==-1)//创建一个wave格式语音文件
{
    perror("cannot creat the sound file");
}
if((status = write(fd_f, &wavehead, sizeof(wavehead)))==-1)//写入wave文件的文件头
{
   perror("write to sound'head wrong!!");
}

while (loops > 0) {
    loops--;
    rc = snd_pcm_readi(handle, buffer, frames);
    if (rc == -EPIPE) {
      /* EPIPE means overrun */
      fprintf(stderr, "overrun occurred\n");
      snd_pcm_prepare(handle);
    } else if (rc < 0) {
      fprintf(stderr,
              "error from read: %s\n",
              snd_strerror(rc));
    } else if (rc != (int)frames) {
      fprintf(stderr, "short read, read %d frames\n", rc);
    }

    if(write(fd_f, buffer, size)==-1)
    {
         perror("write to sound wrong!!");
    }
    if (rc != size)
      fprintf(stderr,
              "short write: wrote %d bytes\n", rc);
}

snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
close(fd_f);

return 0;
}

下载源码

c, 写完程序 在link 时 添加参数 -lasound


版权所有:http://blog.csdn.net/sea918






  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值