Chinaunix首页 | 论坛 | 博客
  • 博客访问: 10781
  • 博文数量: 4
  • 博客积分: 196
  • 博客等级: 入伍新兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-10 19:43
文章分类
文章存档

2011年(4)

我的朋友

分类: WINDOWS

2011-03-28 13:31:13


 

为了理解Mixer API是如何工作的,首先我们得弄清楚一个典型声卡的硬件组成。因此非常有必要去建立一个声卡模型,此声卡应拥有多个典型的组件并且这些组件都是相关联的。

让我们看一个典型的、最基本的声卡。首先,如果声卡能够进行数字化录音,那么典型情况下它就有一个Microphone Input(麦克风传声器,下同)(附有某种前置放大器),同时它还有一个ADC(模数转换器,下同)将麦克风输入的模拟信号转换为数字信号,因此,它就有两个组件——Microphone InputADC。从Microphone Input组件输入的信号输送到ADC。我们可以使用以下的方块图来表示这两个组件,并表明信号在这两个组件之间的传输关系(通过箭头表示)。

" alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1047">

 

一个典型的声卡应该还可以回放数字声音,因此它有一个DAC(数模转换器,下同)组件将数字信号转换回模拟信号,同时它还应有一个Speaker Out(扬声器,下同)(附有某种模拟信号放大器)。因此,它又添加了两个组件——DACSpeaker Out。从DAC输出的信号输送到Speaker Out中。

" alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1025">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1046">

 

一个典型的声卡或许还有其它组件。例如,它或许有一个能播放MIDI音频的内置声音模块(比如Synth(合成器,下同))。这个组件的声音输出同DAC的输出同样输入到Speaker Out组件中。因此,我们的方框图现在是如下的样子:

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1045">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1044">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1026">

 

同样的,一个典型的声卡还有一个内部的连接器连接着计算机的CDROM驱动器的声音输出(这样就可以通过扬声器来播放CDROM里的CD)。与SynthDAC一样,这个组件的输出会输入到Speaker Out。现在,我们的方块图就成了如下的样子:

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1027">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1028">

" alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1029">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1030">

 

 

最后,我们假设这个声卡还有一个Line In(线路输入,下同)组件,因此其它外部的录音机或音频设备或外部的硬件混音器就能够连接到此插孔并将其输入信号数字化。同Microphone Input组件一样,这个组件的输出会输送到ADC组件。下面是我们最终的方块图,其中包括7个组件(和5个信号流向线图——也就是将各个组件相连的箭头线)

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1031">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1032">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1033">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1034">

alt="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" title="混音器原理及Mixer API函数介绍1 - 我,猪八戒 - 我,猪八戒的博客" v:shapes="_x0000_i1035">

 

典型情况下,每个组件都有它自己的参数。例如,Synth通常会有它的音量参数。Internal CD Audio同样有它自己的音量参数。DAC也会有它自己的音量参数。在这种方式下,如果用户同时播放一个Audio CD、一个MIDI文件和一个WAVE文件,他可以分别调整这三个组件输入到Speaker Out的音量。同样的,Speaker Out组件也有它自己的音量参数——控制上述3个输入组件最终输出的主音量。

同样的,Line InMicrophone Input组件也都有各自的音量参数,这样在同时录音的情况下,就可以平衡二者的输入。ADC组件有个主音量参数,它控制着上述2个连接到它的输入组件的录音音量。

一个给定的组件还拥有其它可控的参数。例如,上述每个组件都有各自的用于快速打开或关闭声音的静音(Mute)开关。

混音器设备

系统中每个声卡都有一个与其相连的混音器设备。声卡上所有的组件都由与声卡关联的混音器设备控制。Windows Mixer API就是用来访问声卡的混音器设备的一组函数。Mixer API有一组函数,可以获取声卡上所有的组件并调整它们的参数。这是Win95/98WinNT (4.X 及以上版本)新增的一组API,虽然加入到windows 3.1及更早的版本中也可以使用。

注意:有些声卡的设备驱动需要额外的支持才可以协同Mixer API工作。不是所有的Win95WinNT驱动都支持Mixer API操作。Win3.1驱动不支持Mixer API操作。

在一个计算机中,可能安装有一个以上声卡。你或许已经注意到windows在系统中维护了一组WAVEMIDI 输入输出的设备列表。既然每个已安装的声卡都有其对应的混音器设备(只要声卡的驱动支持),windows同样也就维护了一组已安装在系统中的混音器设备。例如,如果你有在系统中安装了两块声卡,那么系统中就应该有两个混音器设备(假设两个声卡的驱动都支持Mixer API)。

       WAVEMIDI输入输出设备一样,windows也会给每个混音器设备赋一个数值ID。因此,系统中的第一个(默认)混音器设备的ID号为0。如果系统中有第二个声卡,那么就有一个ID1的混音器设备。

打开一个混音器设备

怎样在你的程序中选择一个混音器设备来进行操作?这里有很多种方法,具体要看你想做多炫、多灵活的程序了。

如果你只是想简单的打开首选的混音器设备,那么您可以使用mixerOpen函数,并使设备ID0,如下:

unsigned long err;

HMIXER mixerHandle;

 

/* 打开与默认的Audio/MIDI声卡相连的混音器 */

err = mixerOpen(&mixerHandle, 0, 0, 0, 0);

if (err)

{

    printf("ERROR: Can't open Mixer Device! -- %08X\n", err);

}

else

{

/*混音器已打开,你可以此混音器句柄mixerHandle用在其它Mixer API*/

}

     当然,如果没有安装混音器,上述调用将会返回一个错误值,因此要始终检查那个返回值。(调用Mixer API返回的预期错误值已列在头文件MMSYSTEM.H中。不幸的是,不像其它WAVEMIDI那些更低级的API,这里没有将这些错误值代码转换为描述字符串的API函数)。

     但是,什么是首选混音器设备?好,让我来告诉你,那就是第一个安装在系统中的混音器设备。如果系统中只有一个声卡,那么你得到的混音器设备肯定就是首选混音器设备。但是,如果你尝试着去使用第二块声卡上的Wave Output组件,那该怎么做?你肯定不希望使用第一块声卡的混音器设备去控制第二块声卡上的Wave Out组件的音量。(第一块声卡的混音器当然控制不了第二块声卡的Wave Output组件了)。

     但是,你怎样打开与你想要的那块声卡关联的混音器?幸运的是,mixerOpen()函数允许你传递与这个声卡关联的其它设备的ID或句柄来打开混音器。在这种情况下,mixerOpen()函数将会准确无疑的返回与那个声卡的其它设备关联的混音器设备。以下是一个样例程序,展示了如何通过打开默认的WAVE OUT设备(默认声卡上的WAVE OUT设备)获取混音器设备的句柄:

unsigned long err;

HMIXER mixerHandle;

WAVEFORMATEX waveFormat;

HWAVEOUT hWaveOut%

阅读(1459) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~