在Linux中,先后出现了音频设备的两种框架OSS和ALSA
1 OSS(Open Sound System)是unix平台上一个统一的音频接口。
一、基础知识 数字音频设备(有时也称codec,PCM,DSP,ADC/DAC设备):播放或录制数字化的声音。它的指标主要有:采样速率(电话为8K,DVD为96K)、channel数目(单声道,立体声)、采样分辨率(8-bit,16-bit)。 mixer(混频器):用来控制多个输入、输出的音量,也控制输入(microphone,line-in,CD)之间的切换。 synthesizer(合成器):通过一些预先定义好的波形来合成声音,有时用在游戏中声音效果的产生。 MIDI 接口:MIDI接口是为了连接舞台上的synthesizer、键盘、道具、灯光控制器的一种串行接口。 在Unix系统中,所有的设备都被统一成文件,通过对文件的访问方式(首先open,然后read/write,同时可以使用ioctl读取/设置参数,最后close)来访问设备。在OSS中,主要有以下的几种设备文件:
/********************************************************************************
** 音频设备的操作-->OSS
**
**----------FIleInof------------------------------------------------------------
** 文件信息:
** 创建日期:2014-10-8
** 修改日期:
** 文件信息:有bug
********************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
int rate = 88200; //立体声
int bit = 16;
if(argc < 2){
printf("input : ./app music\n");
exit(1);
}
int fd = open("/dev/dsp",O_RDWR);
if(fd < 0){
perror("open error\n");
exit(1);
}
int io_1 = ioctl(fd,SOUND_PCM_WRITE_BITS,&bit);
if(io_1 < 0){
perror("ioctl_1 error!\n");
exit(1);
}
int io_2 = ioctl(fd,SOUND_PCM_WRITE_RATE,&rate);
if(io_2 < 0){
perror("ioctl_2 error!\n");
exit(1);
}
/*打开音乐文件*/
int fp = open(argv[1],O_RDWR);
if(fp < 0){
perror("open fp error!\n");
exit(1);
}
/*求文件的大小*/
struct stat music_buf;
int ft = fstat(fd,&music_buf);
if(ft < 0){
perror("fstat error!\n");
exit(1);
}
int len = music_buf.st_size;
char *buf = (char *)malloc(sizeof(char)*len);
memset(buf,0,len);
/*读文件到buf中*/
int rd = read(fp,buf,len);
if(rd < 0){
perror("read error!\n");
exit(1);
}
int wr = write(fd,buf,len);
if(wr < 0){
perror("write error!\n");
exit(1);
}
free(buf);
buf = NULL;
close(fd);
close(fp);
return 0;
}
2 alsa音频设备的操作
编程的一般步骤:设置参数到设备中--->音源处理--->写入设备
放音程序:
/********************************************************************************
** 音频设备的操作-->alsa
**
**----------FIleInof------------------------------------------------------------
** 文件信息:
** 创建日期:2014-10-8
** 修改日期:
** 文件信息:放音的操作
********************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
if(argc < 2){
printf("input :./app music");
exit(1);
}
snd_pcm_hw_params_t *myparams;
snd_pcm_t *mydevice;
snd_pcm_uframes_t frame = 200;
int fd = snd_pcm_open(&mydevice,"default",0,0);
if(fd < 0){
perror("open error!\n");
exit(1);
}
/*分配空间*/
snd_pcm_hw_params_malloc(&myparams);
/*初始化*/
int init = snd_pcm_hw_params_any(mydevice,myparams);
if(init < 0){
perror("any error!\n");
exit(1);
}
//设置位宽
snd_pcm_hw_params_set_format(mydevice,myparams,SND_PCM_FORMAT_S16_LE);
//设置声道
snd_pcm_hw_params_set_channels(mydevice, myparams, 2); //2代表立体声
//设置采样率
int rate = 44100;
int dir;
snd_pcm_hw_params_set_rate_near(mydevice,myparams,&rate,&dir);
//设置交互模式
snd_pcm_hw_params_set_access(mydevice,myparams,SND_PCM_ACCESS_MMAP_INTERLEAVED);
//设置采样周期
snd_pcm_hw_params_set_period_size_near(mydevice,myparams,&frame, &dir);
snd_pcm_hw_params_get_period_size(myparams,&frame, &dir);
//设置参数
snd_pcm_hw_params(mydevice,myparams);
int fp = open(argv[1],O_RDWR);
if(fp < 0){
perror("open error!\n");
exit(1);
}
int len = lseek(fp,0,SEEK_END);
if(len < 0){
perror("lseek error!\n");
exit(1);
}
lseek(fp,0,SEEK_SET);
char *music = (char *)malloc(sizeof(char) *len);
/*读取数据*/
int rd = read(fp,music,len);
if(rd < 0){
perror("read error!\n");
exit(1);
}
/*写入设备*/
snd_pcm_writei(mydevice,music,len);
snd_pcm_hw_params_free(myparams);
free(music);
music = NULL;
snd_pcm_close(mydevice);
close(fd);
return 0;
}
录音程序:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char**argv)
{
if(argc < 2){
printf("please input :./app music\n");
exit(1);
}
snd_pcm_hw_params_t *myparams;
snd_pcm_t *mydevice;
snd_pcm_uframes_t frame = 200;
int fd = snd_pcm_open(&mydevice,"default",1,0);
if(fd < 0){
perror("open \n");
exit(1);
}
snd_pcm_hw_params_malloc(&myparams);
int init = snd_pcm_hw_params_any(mydevice, myparams);
if(init < 0){
perror("init\n");
exit(1);
}
//设置位宽
snd_pcm_hw_params_set_format(mydevice, myparams, SND_PCM_FORMAT_S16);
//设置声道
snd_pcm_hw_params_set_channels(mydevice, myparams,2);
//设置采样率
int rate = 44100;
int dir ;
snd_pcm_hw_params_set_rate_near(mydevice, myparams, &rate, &dir);
//设置交互模式
snd_pcm_hw_params_set_access(mydevice, myparams, SND_PCM_ACCESS_MMAP_INTERLEAVED);
//获取周期
snd_pcm_hw_params_set_period_size_near(mydevice, myparams, &frame, &dir);
snd_pcm_hw_params_get_period_size(myparams, &frame, &dir);
//设置参数
snd_pcm_hw_params(mydevice, myparams);
int fp = open(argv[1],O_RDWR);
if(fp < 0){
perror("open music\n");
exit(1);
}
int len = 10*44100*2*16/8;
char *music = (char *)malloc(sizeof(char )*len);
int l = 0;
int i = 0;
while(l < len){
snd_pcm_readi(mydevice, music + i*4*frame, frame);
l = i*4*frame + 4*frame;
i++;
}
int rd = write(fp,music,len);
if(rd < 0){
perror("read\n");
exit(1);
}
snd_pcm_hw_params_free(myparams);
free(music);
close(fp);
snd_pcm_close(mydevice);
return 0;
}