2. 对声卡编程
只要我们不是进行诸如驱动设备开发之类的工作,对声卡的编程和上面对扬声器的编程没有什么本质的区别。当你试图来编
写诸如CD播放器、MP3播放器之类的复杂的程序时,你的工作是取获得与CDROM控制、MP3解码之类的信息,而读写系统设备的这一步在Linux下超
互想象的简单。例如,Linux下最简单的播放wav的程序只有一行:cp $<
>/dev/audio。将它写成一个shell文件,同样是一个程序(shell 编程)。
我们首先需要知道一台机器上是否
有声卡,一个检查的办法是检查文件/dev/sndstat文件,如果打开此文件错误,并且错误号是ENODEV,则说明此机器没有安装声卡。除此之外,
试着去打开文件/dev/dsp也可以来检查是否安装了声卡。
Linux下和声卡相关的文件有许多,如采集数字样本的/dev
/dsp文件,针对混音器的/dev/mixer文件以及用于音序器的/dev
/sequencer等。文件/dev/audio是一个基于兼容性考虑的声音设备文件,它实际是到上述数字设备的一个映射,它最大的特色或许是对诸如
wav这类文件格式的直接支持。我们下面的例子即使用了此设备文件实现了一个简单的录音机:我们从声卡设备(当然要用麦克风)读取音频数据,并将它存放到
文件test.wav中去。要播放这个wav文件,只要如前面所述,使用命令cp test.wav
>/dev/audio即可,当然你也可以用Linux下其他的多媒体软件来播放这个文件。
下面即是完整的程序清单:
/*
此文件中定义了下面所有形如SND_的变量*/
#include
#include
#include
#include
#include
main(
)
{
/* id:读取音频文件描述符;fd:写入的文件描述符。i,j为临时变量*/
int id,fd,i,j;
/*
存储音频数据的缓冲区,可以调整*/
char testbuf[4096];
/* 打开声卡设备,失败则退出*/
if ( (
id = open ( "/dev/audio", O_RDWR ) ) < 0 ) {
fprintf (stderr, "
Can?t open sound device!\n");
exit ( -1 ) ;
}
/* 打开输出文件,失败则退出*/
if
( ( fd = open ("test.wav",O_RDWR))<0){
fprintf ( stderr, " Can?t
open output file!\n");
exit (-1 );
}
/* 设置适当的参数,使得声音设备工作正常*/
/*
详细情况请参考Linux关于声卡编程的文档*/
i=0;
ioctl (id,SNDCTL_DSP_RESET,(char
*)&i) ;
ioctl (id,SNDCTL_DSP_SYNC,(char *)&i);
i=1;
ioctl
(id,SNDCTL_DSP_NONBLOCK,(char *)&i);
i=8000;
ioctl
(id,SNDCTL_DSP_SPEED,(char *)&i);
i=1;
ioctl
(id,SNDCTL_DSP_CHANNELS,(char *)&i);
i=8;
ioctl
(id,SNDCTL_DSP_SETFMT,(char *)&i);
i=3;
ioctl
(id,SNDCTL_DSP_SETTRIGGER,(char *)&i);
i=3;
ioctl
(id,SNDCTL_DSP_SETFRAGMENT,(char *)&i);
i=1;
ioctl
(id,SNDCTL_DSP_PROFILE,(char *)&i);
/* 读取一定数量的音频数据,并将之写到输出文件中去*/
for
( j=0; j<10;){
i=read(id,testbuf,4096);
if(i>0){
write(fd,filebuf,i);
j++;
}
}
/*
关闭输入、输出文件*/
close(fd);
close(id);
}
#include
#include
#include
#include
#include
main()
{
int id,fd,i,j;
char
testbuf[4096];
id=open("/dev/audio",O_RDWR);
fd=open("test.wav",O_RDWR);
if(id<0||fd<0){
printf("error in open the device!\n");
printf("id %d\t dsp%d\t
seq%d\n",id,dsp,seq);
exit(-1);
}
post=0;
ioctl(id,SNDCTL_DSP_RESET,(char *)&i);
ioctl(id,SNDCTL_DSP_SYNC,(char *)&i);
i=1;
ioctl(id,SNDCTL_DSP_NONBLOCK,(char *)&i);
i=8000;
ioctl(id,SNDCTL_DSP_SPEED,(char *)&i);
i=1;
ioctl(id,SNDCTL_DSP_CHANNELS,(char *)&i);
i=8;
ioctl(id,SNDCTL_DSP_SETFMT,(char *)&i);
i=3;
ioctl(id,SNDCTL_DSP_SETTRIGGER,(char *)&i);
i=3;
ioctl(id,SNDCTL_DSP_SETFRAGMENT,(char *)&i);
i=1;
ioctl(id,SNDCTL_DSP_PROFILE,(char *)&i);
for(j=0;j<10;){
i=read(id,testbuf,4096);
if(i>0){
write(fd,filebuf,i);
j++;
}
}
close(fd);
close(id);
}
该程序只是简单地录一小段纯音频数据存储在test.wav中,用命令
cat
test.wav >/dev/audio 就可以播放出来
一个不成功的案例:::::
lame_global_flags
*gf;
int lame_encoder(FILE* OutFileID, void
*WAVBuffer, long WAVBufferSize)
{
unsigned
char mp3buffer[LAME_MAXMP3BUFFER];
int imp3;
int frames;
if (WAVBufferSize <= 0)
return -1;
void *tmpBuf =
malloc(WAVBufferSize);
memcpy(tmpBuf, WAVBuffer,
WAVBufferSize);
// encode until we hit eof
// read in 'iread' samples
if (gf ==
NULL)
return -1;
frames =
lame_get_frameNum(gf);
// encode
imp3
= lame_encode_buffer(gf, WAVBuffer, WAVBuffer, WAVBufferSize,
mp3buffer, sizeof(mp3buffer));
free(tmpBuf);
// was our output buffer big enough?
if (imp3 < 0) {
if (imp3
== -1)
fprintf(stderr, "mp3
buffer is not big enough... \n");
else
fprintf(stderr, "mp3
internal error: error code=%i\n", imp3);
return 1;
}
if
(fwrite( mp3buffer, imp3, 1, OutFileID) != imp3){
fprintf(stderr, "Error writing mp3 output \n");
return 1;
}
return 0;
}
int
InitMP3Convert(void)
{
// support for "nogap" encoding
of up to 200 .wav files//
#define MAX_NOGAP 200
if (NULL == (gf = lame_init())) {
fprintf(stderr, "fatal error during initialization\n");
return 1;
}
lame_set_num_channels(gf,2);
lame_set_in_samplerate(gf,44100);
lame_set_brate(gf,128);
lame_set_mode(gf,1);
lame_set_quality(gf,2);
lame_init_params( gf);
return 0;
}
void FinishConvert(FILE *fid)
{
lame_mp3_tags_fid(gf,fid);
}
void DeinitMP3Convert()
{
lame_close(gf);
}
数据是从WAV文件获得或是从麦克风获得的。但是在压缩成mp3以后,除了很多杂音,其余什么都没有
阅读(1808) | 评论(0) | 转发(0) |