DSP

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%