关闭

Linux音频编程2 音频录放框架

381人阅读 评论(0) 收藏 举报
音频录放框架
下面给出一个利用声卡上的DSP设备进行声音录制和回放的基本框架,它的功能是先录制几秒种音频数据,将其存放在内存缓冲区中,然后再进行回放,其所有的功能都是通过读写/dev/dsp设备文件来完成的:
 
/*
 * sound.c
 */
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
 
#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:\n");
    status = read(fd, buf, sizeof(buf)); /* 录音 */
    if (status != sizeof(buf))
      perror("read wrong number of bytes");
 
    printf("You said:\n");
    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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/soundcard.h>
 
/* 用来存储所有可用混音设备的名称 */
const char *sound_device_names[] = SOUND_DEVICE_NAMES;
 
int fd;                  /* 混音设备所对应的文件描述符 */
int devmask, stereodevs; /* 混音器信息对应的位图掩码 */
char *name;
 
/* 显示命令的使用方法及所有可用的混音设备 */
void usage()
{
 int i;
 
 fprintf(stderr, "usage: %s <device> <left-gain%%> <right-gain%%>\n"
       "       %s <device> <gain%%>\n\n"
       "Where <device> is one of:\n", name, name);
 for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++)
    if ((1 << i) & devmask) /* 只显示有效的混音设备 */
      fprintf(stderr, "%s ", sound_device_names[i]);
 fprintf(stderr, "\n");
 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\n", 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\n", 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%%\n", dev, left, right);
 
 /* 关闭混音设备 */
 close(fd);
 return 0;
}
 
编译好上面的程序之后,先不带任何参数执行一遍,此时会列出声卡上所有可用的混音通道:
 
[xiaowp@linuxgam sound]$ ./mixer
usage: ./mixer <device> <left-gain%> <right-gain%>
       ./mixer <device> <gain%>
Where <device> 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%

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:117691次
    • 积分:1408
    • 等级:
    • 排名:千里之外
    • 原创:8篇
    • 转载:109篇
    • 译文:0篇
    • 评论:47条
    最新评论