使用mci播放多媒体

 这里讲讲使用MCI播放音频文件,MCI为程序员提供了两种方式访问MCI设备或文件:一种是基于消息的命令接口函数;另一种是使用字符串接口函数。两者的区别在于基本命令结构和发送信息到设备的原理。

◆、基于消息的MCI

    消息命令控制接口使用消息控制MCI设备,将消息和控制信息以数据结构的形式作为函数参数发送,并接收返回的数据,MCI直接把设备消息和控制消息发送到设备。一条基于MCI的命令包含以下3个部分。

  • 数据结构:该结构包含可传递给MCI驱动程序的信息和从驱动程序返回的值,指定要执行的MCI命令一个常量,如MCI_OPEN、MCI_CLOSE...
  • 一个或一组用来指定MCI信息子选项的标志:这些标志用来确定可以得到什么类型的信息和如何执行函数。
  • 一个确定命令附加参数:Windows MDK为使用命令消息接口发送MCI消息提供了3个核心函数。

1、mciSendCommand函数。该函数用于向MCI设备发送一个命令消息,原型为:
MCIERROR  mciSendCommand(MCIDEVICEID IDDevice, UINT uMsg, DWORD fdwCommand, DWORD dwParam);
参数说明如下:
IDDevice:用来表示一个MCI设备。MCI使用MCI_OPEN消息打开一个设备时自动创建一个标识号用以唯一标识要操作的设备,以后的命令操作均使用此标识。
uMsg:表示要发出的消息,取值如下所示。
        MCI_OPEN        打开一个设备
        MCI_CLOSE       关闭一个设备
        MCI_PLAY        播放全部或部分音频,从暂停状态恢复播放
        MCI_STOP        停止播放
        MCI_PAUSE       暂停播放
        MCI_SEEK        改变当前位置
        MCI_CUE         提示一个设备以最小的延迟开始播放或录制
        MCI_RECORD      在一个设备上开始录制
        MCI_SAVE        保存一个文件
        MCI_INFO        查询设备信息,如产品名称等
        MCI_GETDEVCAPS  查询产品特征,如设备类型等
        MCI_STATUS      查询设备当前状态,如播放位置、媒体格式等
        MCI_SET  设置设备参数,如时间格式、波形数据格式等
fdwCommand:消息指定标志。
dwParam:指定一个指向消息数据结构的指针。
    如果mciSendCommand函数调用成功则返回0,否则返回错误代码消息。所返回的DWORD低位字是错误代码,可以将它发送到mciGetErrorString函数,已获得对错误的文本描述。若错误事设备特有的,高位包含了设备ID,否则高位为0。
    MMSYSTEM.H头文件中还定义了MCI命令所需要的数据结构类型。以下是MCI命令常用的数据结构。
        MCI_OPEN_PARMS     MCI_OPEN命令消息参数的数据结构
        MCI_PLAY_PARMS     MCI_PLAY命令消息参数的数据结构
        MCI_RECORD_PARMS   MCI_RECORD命令消息参数的数据结构

2、mciGetDevicelID函数。当打开一个设备时,该函数用来获得此设备的ID,原型为:
MCIDEVICEID  mciGetDevicelID(LPCTSTR lpszDevice);
参数lpszDevice指定要打开的MCI设备名。若函数调用成功,则返回设备的标志号,否则返回0。

3、mciGetErrorString函数。该函数用于返回一个错误代码的文本描述,原型为:
BOOL  mciGetErrorString(DWORD fdwError, LPTSTR lpszErrorText, UINT cchErrorText);
参数说明如下:
fdwError:上一次mciSendCommand函数调用的返回值。
lpszErrorText:用来接收返回的文本描述的缓冲区指针。
cchErrorText:指定lpszErrorText的长度。

◆、基于字符串的MCI

    命令字符串接口使用文本命令控制MCI设备。文本串中包含执行一个命令所需要的所有信息。MCI分析文本串,并把它翻译成命令消息接口中的消息和控制信息。由于加入了翻译过程,命令字符串接口的速度要慢于命令消息接口。

     Windows也为字符串接口定义了3个核心操作函数。

1、mciSendString函数。该函数用于向一个MCI的设备驱动程序发送一个字符串,原型为:
MCIERROR  mciSendString(LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, HANDLE hwndCallback);
参数说明如下:
lpszCommand:一个以NULL结尾的定义MCI控制命令的字符串,格式为:command device_name argument
lpszReturnString:一个远指针,它指向由应用程序返回的字符串缓冲区。
cchReturn:指定了缓冲区大小。
hwndCallback:用来指定接收并处理MCI向应用程序发出的MM_MCINOTIFY消息窗口的句柄。
函数成功调用,则返回0,否则返回错误代码。可以将错误代码传递给mciGetErrorString函数获得对错误的文本描述。

2、mciGetErrorString函数。前面已作了介绍,这里不再叙述。

3、mciExecute函数。实际上是mciSendString函数的简化形式,它不占用缓冲区来返回消息。如果调用失败,则显示出错信息消息框,原型为:
BOOL  FAR  PASCAL  mciExecute(LPCTSTR lpszDevice);
参数lpszDevice与mciSendString函数的第一个参数含义相同。

    使用MCI对多媒体进行操作实际上是向设备发送相应的命令。下面介绍各种常用的操作。

◆、打开多媒体设备

    使用MCI_OPEN命令消息来打开设备。所有的设备对于MCI命令都需要一个指向消息命令数据结构MCI_OPEN_PARMS的指针。该结构格式如下:
typedef struct _MCI_OPEN_PARMS
{
    DWORD dwCallback;         //设置MCI_NOTIFY标志时的回调窗口句柄
    MCIDEVICEID wDeviceID;    //打开设备成功时返回的设备标识号
    LPCSTR lpstrDeviceType;   //指定所要打开设备类型
    LPCSTR lpstrElementName;  //对于复合设备,指定设备元素
    LPCSTR lpstrAlias;        //设备别名
} MCI_OPEN_PARMS;

    简单设备和复合设备打开方式有所不同。打开简单设备时,不需要指定设备元素。可以用3种方法打开一个简单设备。


1、指定设备名。下面一段代码通过指定设备名打开一个光盘设备。
WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
//为MCI_OPEN消息数据结构赋值
mciOpenParms.lpstrDeviceType = "cdaudio";
//通过指定设备名打开光盘设备
if (micSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPVOID)&mciOpenParms))
    //调用失败的处理
else
    wDeviceID = mciOpenParms.wDeviceID;

2、指定设备驱动程序。下面一段代码通过指定设备的驱动程序打开一个光盘设备。
WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
//为MCI_OPEN消息数据结构赋值
mciOpenParms.lpstrDeviceType = "mcicd.drv";
//通过指定设备名打开光盘设备
if (micSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPVOID)&mciOpenParms))
    //调用失败的处理
else
    wDeviceID = mciOpenParms.wDeviceID;

3、指定设备类型参数。各个MCI设备的设备类型常量如下所示。
MCI命令能够管理的音频设备类型所对应的字符串和常量
    cdaudio            MCI_DEVTYPE_CD_AUDIO
    waveaudio          MCI_DEVTYPE_WAVEFORM_AUDIO
    sequencer          MCI_DEVTYPE_SEQUENCER
    animation          MCI_DEVTYPE_ANIMATION
    dat                MCI_DEVTYPE_DAT
    digitalvideo       MCI_DEVTYPE_DIGITAL_VIDEO
    other              MCI_DEVTYPE_OTHER
    scanner            MCI_DEVTYPE_SCANNER
    vcr                MCI_DEVTYPE_VCR
    videodisc          MCI_DEVTYPE_VIDEODISC
下面一段代码通过指定设备的类型参数打开一个光盘设备。
WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
//为MCI_OPEN消息数据结构赋值
mciOpenParms.lpstrDeviceType = (LPRSTR) MCI_DEVTYPE_CD_AUDIO;
//通过指定设备名打开光盘设备
if (micSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPVOID)&mciOpenParms))
    //调用失败的处理
else
    wDeviceID = mciOpenParms.wDeviceID;

    打开复合设备需要指定设备元素,也可以用3种方法打开一个复合设备。

1、只指定设备。该方法类似于打开简单设备,但只适合用于MCI_GETDEVCAPS命令确定设备性能。

2、同时指定设备和设备元素。该方法需要指出设备元素。举例如下:
WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
//为MCI_OPEN消息数据结构赋值
mciOpenParms.lpstrElementName = "c:/windows/media/chorcd.wav";
//通过指定设备元素参数打开复合设备
if (micSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPVOID)&mciOpenParms))
    //调用失败的处理
else
    wDeviceID = mciOpenParms.wDeviceID;

3、只指定设备元素。在此方式下,MCI根据WIN.INI文件中的[mci extension]字段,从设备的扩展名确定设备。例如:
#define wPtnLength 255;           //缓冲区大小
char lpstrRtnString[wPtnLength];   //指向缓冲区指针
WORD result;
result = mciSendString("open cdaudio", lpstrRtnString, wPtnLength, NULL);
//打开CD设备
if (result != 0)
    mciGetErrorString(result, lpstrRtnString, wPtnLength)
    //事件处理
else
    //设备成功打开后事件处理

下面一段代码用来打开一个多媒体复合设备。
#define wPtnLength 255;           //缓冲区大小
char lpstrRtnString[wPtnLength];   //指向缓冲区指针
WORD result;
result = mciSendString("c:/windows/media/chorcd.wav", lpstrRtnString, wPtnLength, NULL);
//打开CD设备
if (result != 0)
    mciGetErrorString(result, lpstrRtnString, wPtnLength)
    //事件处理
else
    //设备成功打开后事件处理

◆、播放多媒体设备

        在成功打开设备后,应用程序就可以通过向MCI发送MCI_PLAY或play字符串命令来播放多媒体设备。MCI_PLAY的数据结构MCI_PLAY_PARMS的格式如下:
typedef struc{
    DWORD dwCallback;    //设置MCI_NOTIFY标志时回调窗口句柄
    DWORD dwFrom;        //播放的起始位置
    DWORD dwTo;          //播放的结束位置
} MCI_PLAY_PARMS;
    下面一段代码用来播放已打开的MCI设备。

WORD wDeviceID;
MCI_PLAY_PARMS mciPlayParams;
//为MCI_PLAY消息数据结构赋值
mciSendCommand(wDeviceID, MCI_PLAY, 0, (DWORD)(LPVOID)&mciPlayParams);

    若不给MCI_PLAY_PARMS数据结构中的dwFrom和dwTo字段赋值,播放从头至尾进行。
    而在使用play字符串命令时,如果play命令不加任何参数,则多媒体设备会从目前的位置播放到媒体或文件的结束。play命令支持From和To两个参数,它们分别指向起始和终止位置。实例如下:

#define wPtnLength 255;           //缓冲区大小
char lpstrRtnString[wPtnLength];   //指向缓冲区指针
//播放CD从第10秒到第15秒位置
mciSendString("play cdaudio from 10000 to 15000", lpstrRtnString, wPtnLength, NULL);

 ◆、关闭媒体设备

    应用程序在使用完一个打开的多媒体设备后,必须向MCI发送一个MCI_CLOSE消息来关闭设备。应该注意的是,在应用程序退出之前,应关闭所有的MCI设备。这时可以使用MCI_ALL_DEVICE_ID常量,只需一条命令就关闭所有的多媒体设备。下面一段代码演示了关闭所有设备。

mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, 0, NULL);

也可以使用close字符串命令关闭使用完的MCI设备。例如:

#define wPtnLength 255;           //缓冲区大小
char lpstrRtnString[wPtnLength];   //指向缓冲区指针
mciSendString("close cdaudio", lpstrRtnString, wPtnLength, NULL);

    与基于消息的命令一样,在退出应用程序之前,应关闭所有的设备,这时可以使用all参数,实例如下:

#define wPtnLength 255;           //缓冲区大小
char lpstrRtnString[wPtnLength];   //指向缓冲区指针
mciSendString("close all", lpstrRtnString, wPtnLength, NULL);

 ◆、暂停多媒体播放

    暂停多媒体播放可以通过向MCI发送MCI_PAUSE命令实现,实例如下:

WORD wDeviceID;
MCI_PLAY_PARMS mciPlayParam;
mciSendCommand(wDeviceID, MCI_PAUSE, NULL, (DWORD)(LPVOID)&mciPlayParam);

 ◆、获取和设置播放信息

    在播放媒体时,很多时候需要获取播放信息,如波形音频的采样率、通道数和量化位数、CD音频文件总长度等。这时,可以通过向MCI发送MCI_STATUS命令实现。下面一段代码可以用来获取波形音频的采样率和通道数。

WORD wDeviceID;
MCI_STATUS_PARAM StatusParam;
StatusParam.dwItem = MCI_WAVE_STATUS_SAMPLESPERSEC;
mciSendCommand(wDeviceID, MCI_STATUS, MCI_WAIT | MCI_STATUS_ITTEM, &StatusParam);
DWORD samplerate = StatusParam.dwReturn;    //该参数返回采样率
StatusParam.dwItem = MCI_WAVE_STATUS_CHANNLES;
mciSendCommand(wDeviceID, MCI_STATUS, MCI_WAIT | MCI_STATUS_ITTEM, &StatusParam);
DWORD channelnumber = StatusParam.dwReturn;    //该参数返回通道数

    也可以采用字符串命令的方式获得播放信息,实例如下:

MCIERROR mciError;
mciError = mciSendString("open waveaudio", buf, strlen(buf), NULL);

    同样,在进行编程时,有时也需要对媒体设备的一些播放信息进行设置。这可以通过向已经打开的媒体设备发送MCI_SET命令实现。例如下面一段代码用来设置音频的播放格式为毫秒方式。

WORD wDeviceID;
MCI_SET_PARMS SetParam;
SetParam.dwFormat = MCI_FORMAT_MILLISECONDS;
DWORD OpenFlag = mciSendCommand(wDeviceID, MCI_SET, MCI_TIME_FORMT, &SetParam);

    采用字符串命令设置媒体播放格式的代码如下:

MCIERROR mciError;
mciError = mciSendString("Set file format milliseconds", buf, strlen(buf), NULL);

◆、播放的跳转

    在媒体播放过程中进行跳转首先需要声明一个MCI_SEEK_PARMS结构,并使用该结构的dwTo字段设定需要播放的位置,该位置以毫秒为单位。然后通过mciSendCommand函数向指定设备以MCI_TO为标志发送MCI_SEEK命令,如果只需要跳转到文件的开始或结束位置,可以直接使用MCI_SEEK_TO_START和MCI_SEEK_TO_END为标识发送MCI_SEEK命令。例如:

WORD wDeviceID;
int nMinute;      //欲跳转的时间,以分钟为单位
MCI_SEEK_PARMS SeekParam;
SeekParam.dwTo = (nNinute*60+nSecond)*1000;    //跳转的目标时间,以毫秒为单位
mciSendCommand(wDeviceID, MCI_SEEK, MCI_SEEK_TO | MCI_WAIT, (DWORD)(LPVOID)&SetParam);

    下段代码通过MCI_SEEK命令使CD音频在nTrack轨道,第nMinute分钟,第nSecond秒的nFrame帧进行播放。

int nTrack, nMinute, nSecond;
WORD wDeviceID;
MCI_SEEK_PARMS SeekParam;
SeekParam.dwTo = MCI_MAKE_TWSF(nTrack, nMinute, nSecond, nFrame);
mciSendCommand(wDevice, MCI_SEEK, MCI_SEEK_TO | MCI_WAIT, (DWORD)(LPVOID)&SetParam);

◆、波形音频的录制和保存

    在进行波形音频编程时,记录音频设备输入的音频信息也能实现录音功能。可以通过向打开的音频设备发送MCI_RECORD命令实现该功能。例如:

WORD wDeviceID;
MCI_RECORD_PARMS RecordParam;
RecFlag = mciSendCommand(wDeviceID, MCI_RECORD, NULL, &RecordParam);

    此外,保存音频设备的声音数据wav文件可以通过向设备发送MCI_SAVE命令实现。例如:

WORD wDeviceID;
MCI_SAVE_PARMS SaveParam;
SaveParam.lpfilename = (LPCSTR) FileName;
DWORD SaveFlag = mciSendCommand(wDeviceID, MCI_SAVE, MCI_SAVE_FILE | MCI_WAIT, &SaveParam);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值