Linux音频编程2 音频录放框架
2019-07-13 15:00发布
生成海报
音频录放框架
下面给出一个利用声卡上的DSP设备进行声音录制和回放的基本框架,它的功能是先录制几秒种音频数据,将其存放在内存缓冲区中,然后再进行回放,其所有的功能都是通过读写/dev/dsp设备文件来完成的:
/*
* sound.c
*/
#include
#include
#include
#include
#include
#include
#include
#define LENGTH 3 /*
存储秒数
*/
#define RATE 8000 /*
采样频率
*/
#define SIZE 8 /*
量化位数
*/
#define CHANNELS 1 /*
声道数目
*/
/*
用于保存数字音频数据的内存缓冲区
*/
unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];
int main()
{
int fd; /*
声音设备的文件描述符
*/
int arg; /*
用于
ioctl
调用的参数
*/
int status; /*
系统调用的返回值
*/
/*
打开声音设备
*/
fd = open("/dev/dsp", O_RDWR);
if (fd < 0) {
perror("open of /dev/dsp failed");
exit(1);
}
/*
设置采样时的量化位数
*/
arg = SIZE;
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_BITS ioctl failed");
if (arg != SIZE)
perror("unable to set sample size");
/*
设置采样时的声道数目
*/
arg = CHANNELS;
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
if (arg != CHANNELS)
perror("unable to set number of channels");
/*
设置采样时的采样频率
*/
arg = RATE;
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_WRITE ioctl failed");
/*
循环,直到按下
Control-C */
while (1) {
printf("Say something:
");
status = read(fd, buf, sizeof(buf)); /*
录音
*/
if (status != sizeof(buf))
perror("read wrong number of bytes");
printf("You said:
");
status = write(fd, buf, sizeof(buf)); /*
回放
*/
if (status != sizeof(buf))
perror("wrote wrong number of bytes");
/*
在继续录音前等待回放结束
*/
status = ioctl(fd, SOUND_PCM_SYNC, 0);
if (status == -1)
perror("SOUND_PCM_SYNC ioctl failed");
}
}
4.4
混音器框架
下面再给出一个对混音器进行编程的基本框架,利用它可以对各种混音通道的增益进行调节,其所有的功能都是通过读写/dev/mixer设备文件来完成的:
/*
* mixer.c
*/
#include
#include
#include
#include
#include
#include
/*
用来存储所有可用混音设备的名称
*/
const char *sound_device_names[] = SOUND_DEVICE_NAMES;
int fd; /*
混音设备所对应的文件描述符
*/
int devmask, stereodevs; /*
混音器信息对应的位图掩码
*/
char *name;
/*
显示命令的使用方法及所有可用的混音设备
*/
void usage()
{
int i;
fprintf(stderr, "usage: %s
"
" %s
"
"Where is one of:
", name, name);
for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++)
if ((1 << i) & devmask) /*
只显示有效的混音设备
*/
fprintf(stderr, "%s ", sound_device_names[i]);
fprintf(stderr, "
");
exit(1);
}
int main(int argc, char *argv[])
{
int left, right, level; /*
增益设置
*/
int status; /*
系统调用的返回值
*/
int device; /*
选用的混音设备
*/
char *dev; /*
混音设备的名称
*/
int i;
name = argv[0];
/*
以只读方式打开混音设备
*/
fd = open("/dev/mixer", O_RDONLY);
if (fd == -1) {
perror("unable to open /dev/mixer");
exit(1);
}
/*
获得所需要的信息
*/
status = ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask);
if (status == -1)
perror("SOUND_MIXER_READ_DEVMASK ioctl failed");
status = ioctl(fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs);
if (status == -1)
perror("SOUND_MIXER_READ_STEREODEVS ioctl failed");
/*
检查用户输入
*/
if (argc != 3 && argc != 4)
usage();
/*
保存用户输入的混音器名称
*/
dev = argv[1];
/*
确定即将用到的混音设备
*/
for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++)
if (((1 << i) & devmask) && !strcmp(dev, sound_device_names[i]))
break;
if (i == SOUND_MIXER_NRDEVICES) { /*
没有找到匹配项
*/
fprintf(stderr, "%s is not a valid mixer device
", dev);
usage();
}
/*
查找到有效的混音设备
*/
device = i;
/*
获取增益值
*/
if (argc == 4) {
/*
左、右声道均给定
*/
left = atoi(argv[2]);
right = atoi(argv[3]);
} else {
/*
左、右声道设为相等
*/
left = atoi(argv[2]);
right = atoi(argv[2]);
}
/*
对非立体声设备给出警告信息
*/
if ((left != right) && !((1 << i) & stereodevs)) {
fprintf(stderr, "warning: %s is not a stereo device
", dev);
}
/*
将两个声道的值合到同一变量中
*/
level = (right << 8) + left;
/*
设置增益
*/
status = ioctl(fd, MIXER_WRITE(device), &level);
if (status == -1) {
perror("MIXER_WRITE ioctl failed");
exit(1);
}
/*
获得从驱动返回的左右声道的增益
*/
left = level & 0xff;
right = (level & 0xff00) >> 8;
/*
显示实际设置的增益
*/
fprintf(stderr, "%s gain set to %d%% / %d%%
", dev, left, right);
/*
关闭混音设备
*/
close(fd);
return 0;
}
编译好上面的程序之后,先不带任何参数执行一遍,此时会列出声卡上所有可用的混音通道:
[xiaowp@linuxgam sound]$ ./mixer
usage: ./mixer
./mixer
Where is one of:
vol pcm speaker line mic cd igain line1 phin video
之后就可以很方便地设置各个混音通道的增益大小了,例如下面的命令就能够将CD输入的左、右声道的增益分别设置为80%和90%:
[xiaowp@linuxgam sound]$ ./mixer cd 80 90
cd gain set to 80% / 90%
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮