原文地址:http://blog.csdn.net/suer0101/article/details/7263950
采用OSS进行音频编程时应当遵循的一般性框架:
(1)打开音频设备;
(2)设置采样格式(即量化位数);
(3)设置声道数(单声道或者立体声);
(4)设置采样率(即采样速度);
(5)从设备读入数据或者向设备写入数据;
(6)关闭音频设备;
上述过程中,第(6)可选,因为在进程正常或非正常退出时都会关闭它所打开的文件描述字,这样也就把音频设备的资源释放了。但是,除此之外的五个步骤是不能缺少的,并且顺序也不能颠倒(OSS编程指南对此的说明是:在指定声道数之前设置采样率不能在所有的音频硬件上工作——如果在将声卡设置为高采样率模式之后更改了声道数,应用程序将出现不正确的行为。同时,必须在使用read()或者write()调用读写数据之前设置采样率)。
这是作者编写的一个读写/dev/dsp设备的小程序,可以用它来录制一段声音,也可以用来将录制到文件中的声音播放出来。除此之外,还可以通过命令行参数指定设备参数,如:采样率、量化位数、声道数、要录制的声音长度,等等。详细的命令行参数解释如下:
SndKit [-h] [-d device] [-c channel] [-b bits] [-f hz] [-l len] <-r|-p file>
其中:
¨ -h:打印帮助信息;
¨ -d:指定要读写的音频设备(默认为/dev/dsp);
¨ -c:指定使用的声道数(默认为MONO,单声道);
¨ -b:指定量化位数(默认为8位无符号整数);
¨ -f:指定采样频率(默认为8KHz);
¨ -l:指定录制的声音文件的长度(默认为1024,单位为KB);
¨ -r file:录制声音,file存放录制的声音数据;
¨ -p file:播放file文件中存储的声音数据。
注意:-h,-r,-p这三个选项不能同时出现在命令行上。比如,可以通过下面的命令录制一段声音:
[root@cyc source]# ./SndKit -c 2 -b 16 -f 48 -r cyc.wav
采用的是双声道立体声、16位量化位数、48KHz采样频率、录制的声音保存在cyc.wav文件中,要录制的声音长度采用默认值1024KB。录制好之后,可以通过下面的命令播放出来:
[root@cyc source]# ./SndKit -c 2 -b 16 -f 48 -p cyc.wav
sound data play complete!
需要注意的是,录制时采用的是什么样的参数,播放时就应该采用同样的参数,否则将会出错。
下面直接给出源代码:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include /*for OSS style sound programing */
-
#define TRUE 1
-
#define FALSE 0
-
#define FMT8BITS AFMT_U8 /*unsigned 8 bits(for almost PC) */
-
#define FMT16BITS AFMT_S16_LE /*signed 16 bits,little endian */
-
#define FMT8K 8000 /*default sampling rate */
-
#define FMT11K 11025 /*11,22,44,48 are three pop rate */
-
#define FMT22K 22050
-
#define FMT44K 44100
-
#define FMT48K 48000
-
#define MONO 1
-
#define STEREO 2
-
#define ACT_RECORD 0
-
#define ACT_PLAY 1
-
#define DFT_SND_DEV "/dev/dsp"
-
#define DFT_SND_FMT FMT8BITS
-
#define DFT_SND_SPD FMT8K
-
#define DFT_SND_CHN MONO
-
#define DFT_LEN 1024 /*default record length:40k */
-
#define BUFF_SIZE 512 /*buffer size:512 Bytes */
-
-
void Usage(void);
-
int OpenDevice(const char *, unsigned int);
-
int OpenFile(const char *, unsigned int);
-
int CloseDevice(unsigned int);
-
int CloseFile(unsigned int);
-
-
int main(int argc, char *argv[])
-
{
-
unsigned int snd_fmt = DFT_SND_FMT;
-
unsigned int snd_chn = DFT_SND_CHN;
-
unsigned int snd_spd = DFT_SND_SPD;
-
unsigned char *s_file = NULL;
-
unsigned char *snd_device = DFT_SND_DEV;
-
unsigned int recd_or_play = ACT_PLAY;
-
unsigned char buff[BUFF_SIZE];
-
unsigned long len = DFT_LEN * 1024;
-
int snd_fd;
-
int s_fd;
-
ssize_t n;
-
ssize_t nRD;
-
ssize_t nWR;
-
unsigned int opt_chr;
-
unsigned int opt_err = FALSE;
-
-
optind = 0;
-
while ((opt_chr = getopt(argc, argv, "hd:c:b:f:l:r:p:")) != -1) {
-
switch (opt_chr) {
-
case 'h':
-
Usage();
-
return (0);
-
break;
-
case 'd':
-
snd_device = optarg;
-
break;
-
case 'c':
-
if (atoi(optarg) == 1)
-
snd_chn = MONO;
-
else if (atoi(optarg) == 2)
-
snd_chn = STEREO;
-
else {
-
opt_err = 1;
-
fprintf(stderr, "wrong channel setting,"
-
"should be 1 or 2(default 1,MONO)\n");
-
}
-
break;
-
case 'b':
-
if (atoi(optarg) == 8)
-
snd_fmt = FMT8BITS;
-
else if (atoi(optarg) == 16)
-
snd_fmt = FMT16BITS;
-
else {
-
opt_err = 1;
-
fprintf(stderr, "wrong bits setting,"
-
"should be 8 or 16(default 8)\n");
-
}
-
break;
-
case 'f':
-
if (atoi(optarg) == 8)
-
snd_spd = FMT8K;
-
else if (atoi(optarg) == 11)
-
snd_spd = FMT11K;
-
else if (atoi(optarg) == 22)
-
snd_spd = FMT22K;
-
else if (atoi(optarg) == 44)
-
snd_spd = FMT44K;
-
else if (atoi(optarg) == 48)
-
snd_spd = FMT48K;
-
else {
-
opt_err = 1;
-
fprintf(stderr, "wrong sampling rate,"
-
"should be 8,11,22,or 44(default 8kbps)\n");
-
}
-
break;
-
case 'l':
-
len = atoi(optarg) * 1024;
-
break;
-
case 'r':
-
recd_or_play = ACT_RECORD;
-
s_file = optarg;
-
break;
-
case 'p':
-
recd_or_play = ACT_PLAY;
-
s_file = optarg;
-
break;
-
case '?':
-
opt_err = 1;
-
fprintf(stderr, "unknown option:%c\n", optopt);
-
break;
-
default:
-
opt_err = 1;
-
fprintf(stderr, "getopt error:%d\n", opterr);
-
break;
-
}
-
}
-
-
if (opt_err || argc < 2) {
-
fprintf(stderr, "parse command option failed!!!\n"
-
"run ./SndKit -h for help\n");
-
return (-1);
-
}
-
-
if ((snd_fd = OpenDevice(snd_device, recd_or_play)) < 0) {
-
fprintf(stderr, "cannot open device %s:%s\n", snd_device,
-
strerror(errno));
-
return (-1);
-
}
-
-
if ((s_fd = OpenFile(s_file, recd_or_play)) < 0) {
-
fprintf(stderr, "cannot open sound file %s:%s\n", s_file,
-
strerror(errno));
-
return (-1);
-
}
-
-
if (SetFormat(snd_fd, snd_fmt, snd_chn, snd_spd) < 0) {
-
fprintf(stderr, "cannot set %s in bit %d, channel %d, speed %d\n",
-
snd_device, snd_fmt, snd_chn, snd_spd);
-
return (-1);
-
}
-
-
if (recd_or_play == ACT_RECORD) {
-
n = 0;
-
while (n < len) {
-
nRD = 0;
-
if ((nRD = read(snd_fd, buff, BUFF_SIZE)) < 0) {
-
perror("read sound device failed");
-
return (-1);
-
}
-
if (n + nRD <= len)
-
nWR = nRD;
-
else
-
nWR = len - n;
-
unsigned long old_nWR = nWR;
-
unsigned long t = 0L;
-
-
while (nWR > 0) {
-
if ((t = write(s_fd, buff, nWR)) < 0) {
-
perror("write sound data file failed");
-
return (-1);
-
}
-
nWR -= t;
-
}
-
n += old_nWR;
-
}
-
} else if (recd_or_play == ACT_PLAY) {
-
while (TRUE) {
-
nRD = 0L;
-
if ((nRD = read(s_fd, buff, BUFF_SIZE)) < 0) {
-
perror("read sound data file failed");
-
return (-1);
-
} else if (nRD == 0) {
-
printf("sound data play complete!\n");
-
exit(0);
-
}
-
nWR = nRD;
-
while (nWR > 0) {
-
if ((n = write(snd_fd, buff, nWR)) < 0) {
-
perror("write sound device file failed");
-
return (-1);
-
}
-
nWR -= n;
-
}
-
}
-
}
-
-
CloseDevice(snd_fd);
-
CloseFile(s_fd);
-
return (0);
-
}
-
-
-
-
-
-
-
-
-
-
int OpenDevice(const char *dev_name, unsigned int flag)
-
{
-
int dev_fd;
-
-
if (flag == ACT_RECORD) {
-
if ((dev_fd = open(dev_name, O_RDONLY)) < 0) {
-
return (-1);
-
}
-
} else if (flag == ACT_PLAY) {
-
if ((dev_fd = open(dev_name, O_WRONLY)) < 0) {
-
return (-1);
-
}
-
}
-
return (dev_fd);
-
}
-
-
-
-
-
-
-
-
-
int CloseDevice(unsigned int dev_fd)
-
{
-
return (close(dev_fd));
-
}
-
-
-
-
-
-
-
-
-
-
int OpenFile(const char *file_name, unsigned int flag)
-
{
-
int file_fd;
-
-
if (flag == ACT_RECORD) {
-
if ((file_fd = open(file_name, O_WRONLY)) < 0) {
-
return (-1);
-
}
-
} else if (flag == ACT_PLAY) {
-
if ((file_fd = open(file_name, O_RDONLY)) < 0) {
-
return (-1);
-
}
-
}
-
return (file_fd);
-
}
-
-
-
-
-
-
-
-
-
int CloseFile(unsigned int file_fd)
-
{
-
return (close(file_fd));
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
int SetFormat(unsigned int fd, unsigned int bits, unsigned int chn,
-
unsigned int hz)
-
{
-
int ioctl_val;
-
-
ioctl_val = bits;
-
if (ioctl(fd, SNDCTL_DSP_SETFMT, &ioctl_val) == -1) {
-
fprintf(stderr, "Set fmt to bit %d failed:%s\n", bits,
-
strerror(errno));
-
return (-1);
-
}
-
if (ioctl_val != bits) {
-
fprintf(stderr, "do not support bit %d, supported %d\n", bits,
-
ioctl_val);
-
return (-1);
-
}
-
-
ioctl_val = chn;
-
if ((ioctl(fd, SNDCTL_DSP_CHANNELS, &ioctl_val)) == -1) {
-
fprintf(stderr, "Set Audio Channels %d failed:%s\n", chn,
-
strerror(errno));
-
return (-1);
-
}
-
if (ioctl_val != chn) {
-
fprintf(stderr, "do not support channel %d,supported %d\n", chn,
-
ioctl_val);
-
return (-1);
-
}
-
-
ioctl_val = hz;
-
if (ioctl(fd, SNDCTL_DSP_SPEED, &ioctl_val) == -1) {
-
fprintf(stderr, "Set speed to %d failed:%s\n", hz,
-
strerror(errno));
-
return (-1);
-
}
-
if (ioctl_val != hz) {
-
fprintf(stderr, "do not support speed %d,supported is %d\n", hz,
-
ioctl_val);
-
return (-1);
-
}
-
return (0);
-
}
-
-
-
-
-
-
void Usage(void)
-
{
-
printf
-
("run: ./SndKit [-h] [-d device] [-c channel] [-b bits] [-f hz] [-l len] <-r|-p file>\n"
-
"Description: implent raw sound record/play\n" "option:\n"
-
"\t -h: print help informations\n"
-
"\t -d device: assign sound device to record or playback(default /dev/dsp)\n"
-
"\t -c channel: indicate in MONO or STEREO channel(default MONO)\n"
-
"\t -b bits: assign sampling bits depth(default 8bits unsigned)\n"
-
"\t -f hz: indicate sampling rate,i.e,frequence(default 8kbps)\n"
-
"\t -l len: indicate recording sound's length(default 1024k)\n"
-
"\t -r|-p file: indicate record in or playback(no default,must give out explicitly)\n"
-
"e.g.:\n"
-
"\t ./SndKit -h show help information\n"
-
"\t ./SndKit -r record.wav record audio from microphone(/dev/dsp)\n"
-
"\t ./SndKit -d /dev/dsp -p record.wav playback record.wav via /dev/dsp\n"
-
"\t ./SndKit -b 8 -f 22 -r reacord.wav record audio in 8 bit & 22k hz\n"
-
"\t ./SndKit -d /dev/dsp -c 2 -r record.wav record audio in /dev/dsp and stereo\n"
-
"\t ./SndKit -r -l 40 record.wav record 40k audio data in record.wav\n");
-
}
阅读(954) | 评论(0) | 转发(0) |