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

转载 2012年03月28日 18:23:17
音频录放框架
下面给出一个利用声卡上的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%

相关文章推荐

Linux实现音频录放

走进WAVE文件 WAVE是录音时用的标准的Windows文件格式,文件的扩展名为“wav”,数据本身的格式为PCM或压缩型,属于无损音乐格式的一种,符合RIFF(Resource Intercha...

linux音频编程指南(2)

对声卡进行编程时首先要做的是打开与之对应的硬件设备,这是借助于open系统调用来完成的,并且一般情况下使用的是/dev/dsp文件。采用何种模式对声卡进行操作也必须在打开设备时指定,对于不支持全双工的...

Linux 系统上面的音频编程

  • 2014年05月22日 16:16
  • 451KB
  • 下载

linux ALSA音频驱动框架

ALSA中的链表结构       在ALSA中设计到很多的链表结构,理解这些链表能更好的理解ALSAa)       card->devicescard->devices链表的建立方便了card相关设...

Linux音频编程指南

  • 2011年09月09日 09:12
  • 94KB
  • 下载

收集的linux音频编程文档

  • 2009年08月24日 22:10
  • 619KB
  • 下载

Linux音频设备两种框架OSS和ALSA驱动

在Linux中,先后出现了音频设备的两种框架OSS和ALSA,本节将在介绍数字音频设备及音频设备硬件接口的基础上,展现OSS和ALSA驱动的结构。 17.1~17.2节讲解了音频设备及PCM、IIS和...
  • guoggn
  • guoggn
  • 2015年05月08日 16:33
  • 3027

Linux音频编程指南

  • 2008年01月02日 14:33
  • 124KB
  • 下载

Linux音频编程指南

  • 2010年11月10日 22:59
  • 122KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux音频编程2 音频录放框架
举报原因:
原因补充:

(最多只允许输入30个字)