mixer编程 声卡上的混音器由多个混音通道组成,它们可以通过驱动程序提供的设备文件/dev/mixer进行编程。对混音器的操作一般都通过ioctl()系统调用来完成,所有控制命令都以SOUND_MIXER或者MIXER开头,表17.1列出了常用的混音器控制命令。 表17.1 混音器常用命令 命 令 作 用 SOUND_MIXER_VOLUME 主音量调节 SOUND_MIXER_BASS 低音控制 SOUND_MIXER_TREBLE 高音控制 SOUND_MIXER_SYNTH FM合成器 SOUND_MIXER_PCM 主D/A转换器 SOUND_MIXER_SPEAKER PC喇叭 SOUND_MIXER_LINE 音频线输入 SOUND_MIXER_MIC 麦克风输入 SOUND_MIXER_CD CD输入 SOUND_MIXER_IMIX 放音音量 SOUND_MIXER_ALTPCM 从D/A 转换器 SOUND_MIXER_RECLEV 录音音量 SOUND_MIXER_IGAIN 输入增益 SOUND_MIXER_OGAIN 输出增益 SOUND_MIXER_LINE1 声卡的第1输入 SOUND_MIXER_LINE2 声卡的第2输入 SOUND_MIXER_LINE3 声卡的第3输入 对声卡的输入增益和输出增益进行调节是混音器的一个主要作用,目前大部分声卡采用的是8位或者16位的增益控制器,声卡驱动程序会将它们变换成百分比的形式,也就是说无论是输入增益还是输出增益,其取值范围都是从0到100。 SOUND_MIXER_READ宏 在进行混音器编程时,可以使用 SOUND_MIXER_READ宏来读取混音通道的增益大小,例如如下代码可以获得麦克风的输入增益: ioctl(fd, SOUND_MIXER_READ(SOUND_MIXER_MIC), &vol); 对 于只有一个混音通道的单声道设备来说,返回的增益大小保存在低位字节中。而对于支持多个混音通道的双声道设备来说,返回的增益大小实际上包括两个部分,分 别代表左、右两个声道的值,其中低位字节保存左声道的音量,而高位字节则保存右声道的音量。下面的代码可以从返回值中依次提取左右声道的增益大小: int left, right; left = vol & 0xff; right = (vol & 0xff00) >> 8; SOUND_MIXER_WRITE宏 如果想设置混音通道的增益大小,则可以通过SOUND_MIXER_WRITE宏来实现,例如下面的语句可以用来设置麦克风的输入增益: vol = (right << 8) + left; ioctl(fd, SOUND_MIXER_WRITE(SOUND_MIXER_MIC), &vol); 查询Mixer信息 声卡驱动程序提供了多个ioctl()系统调用来获得混音器的信息,它们通常返回一个整型的位掩码,其中每一位分别代表一个特定的混音通道,如果相应的位为1,则说明与之对应的混音通道是可用的。 通 过 SOUND_MIXER_READ_DEVMASK返回的位掩码查询出能够被声卡支持的每一个混音通道,而通过 SOUND_MIXER_READ_RECMAS返回的位掩码则可以查询出能够被当作录音源的每一个通道。例如,如下代码可用来检查CD输入是否是一个有 效的混音通道: ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask); if (devmask & SOUND_MIXER_CD) printf("The CD input is supported"); 如下代码可用来检查CD输入是否是一个有效的录音源: ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask); if (recmask & SOUND_MIXER_CD) printf("The CD input can be a recording source"); 大 多数声卡提供了多个录音源,通过 SOUND_MIXER_READ_RECSRC可以查询出当前正在使用的录音源,同一时刻可使用2个或2个以上的录音源,具体由声卡硬件本身决定。相应 地,使用 SOUND_MIXER_WRITE_RECSRC可以设置声卡当前使用的录音源,如下代码可以将CD输入作为声卡的录音源使用: devmask = SOUND_MIXER_CD; ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &devmask); 此外,所有的混音通道都有单声道和双声道的区别,如果需要知道哪些混音通道提供了对立体声的支持,可以通过SOUND_MIXER_READ_STEREODEVS来获得。 代码清单17.4的程序实现了利用/dev/mixer接口对混音器进行编程的过程,该程序可对各种混音通道的增益进行调节。 代码清单17.4 OSS mixer接口应用编程范例 1 #include <unistd.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <sys/ioctl.h> 5 #include <fcntl.h> 6 #include <linux/soundcard.h> 7 /* 用来存储所有可用混音设备的名称 */ 8 const char *sound_device_names[] = SOUND_DEVICE_NAMES; 9 int fd; /* 混音设备所对应的文件描述符 */ 10 int devmask, stereodevs; /* 混音器信息对应的bit掩码 */ 11 char *name; 12 /* 显示命令的使用方法及所有可用的混音设备 */ 13 void usage() 14 { 15 int i; 16 fprintf(stderr, "usage: %s <device> <left-gain%%> <right-gain%%>\n" 17 "%s <device> <gain%%>\n\n""Where <device> is one of:\n", name, name); 18 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 19 if ((1 << i) &devmask) 20 /* 只显示有效的混音设备 */ 21 fprintf(stderr, "%s ", sound_device_names[i]); 22 fprintf(stderr, "\n"); 23 exit(1); 24 } 25 26 int main(int argc, char *argv[]) 27 { 28 int left, right, level; /* 增益设置 */ 29 int status; /* 系统调用的返回值 */ 30 int device; /* 选用的混音设备 */ 31 char *dev; /* 混音设备的名称 */ 32 int i; 33 name = argv[0]; 34 /* 以只读方式打开混音设备 */ 35 fd = open("/dev/mixer", O_RDONLY); 36 if (fd == - 1) 37 { 38 perror("unable to open /dev/mixer"); 39 exit(1); 40 } 41 42 /* 获得所需要的信息 */ 43 status = ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask); 44 if (status == - 1) 45 perror("SOUND_MIXER_READ_DEVMASK ioctl failed"); 46 status = ioctl(fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs); 47 if (status == - 1) 48 perror("SOUND_MIXER_READ_STEREODEVS ioctl failed"); 49 /* 检查用户输入 */ 50 if (argc != 3 && argc != 4) 51 usage(); 52 /* 保存用户输入的混音器名称 */ 53 dev = argv[1]; 54 /* 确定即将用到的混音设备 */ 55 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 56 if (((1 << i) &devmask) && !strcmp(dev, sound_device_names[i])) 57 break; 58 if (i == SOUND_MIXER_NRDEVICES) 59 { 60 /* 没有找到匹配项 */ 61 fprintf(stderr, "%s is not a valid mixer device\n", dev); 62 usage(); 63 } 64 /* 查找到有效的混音设备 */ 65 device = i; 66 /* 获取增益值 */ 67 if (argc == 4) 68 { 69 /* 左、右声道均给定 */ 70 left = atoi(argv[2]); 71 right = atoi(argv[3]); 72 } 73 else 74 { 75 /* 左、右声道设为相等 */ 76 left = atoi(argv[2]); 77 right = atoi(argv[2]); 78 } 79 80 /* 对非立体声设备给出警告信息 */ 81 if ((left != right) && !((1 << i) &stereodevs)) 82 { 83 fprintf(stderr, "warning: %s is not a stereo device\n", dev); 84 } 85 86 /* 将两个声道的值合到同一变量中 */ 87 level = (right << 8) + left; 88 89 /* 设置增益 */ 90 status = ioctl(fd, MIXER_WRITE(device), &level); 91 if (status == - 1) 92 { 93 perror("MIXER_WRITE ioctl failed"); 94 exit(1); 95 } 96 /* 获得从驱动返回的左右声道的增益 */ 97 left = level &0xff; 98 right = (level &0xff00) >> 8; 99 /* 显示实际设置的增益 */ 100 fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right); 101 /* 关闭混音设备 */ 102 close(fd); 103 return 0; 104 } 编 译上述程序为可执行文件mixer,执行./mixer <device> <left-gain%> <right-gain%>或./mixer <device> <gain%>可设置增益,device可以是vol、pcm、speaker、line、mic、cd、igain、line1、 phin、video。 |
|