多媒体编程基础.docx
- 文档编号:18121930
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:38
- 大小:314.59KB
多媒体编程基础.docx
《多媒体编程基础.docx》由会员分享,可在线阅读,更多相关《多媒体编程基础.docx(38页珍藏版)》请在冰点文库上搜索。
多媒体编程基础
第六章多媒体编程基础
6.1多媒体文件
多媒体文件一般被称为RIFF文件,即资源交互文件格式(Resourceinterchangefileformat)。
RIFF格式是面向部分(Chunk)的。
一个RIFF文件是由一个或多个部分组成的,每个部分都有一个类型,后面跟着一些数据。
typedefstruct{
FOURCCckID;//4字符字段,标志类型(比如波形音频为WAVE)
DWORDcksize;//部分中数据的大小
}CK;
MFC为处理RIFF文件专门提供了一套多媒体I/O函数,这些函数都有前缀mmio。
比如mmioOpen是打开RIFF文件,mmioDescend可以进入RIFF文件的部分。
HMMIOh;
CStringpath;
……
If((h=mmioOpen(path,NULL,MMIO_READ))==NULL)
returnFALSE;
……
If(mmioRead(h,&dataformat,(long)n)!
=(long)n)
{mmioClose(h,0);
returnFALSE;
}
WAV文件开始是46个字节的文件头,之后是波形数据。
文件头如下:
Typedefstruct{
DWORDrftype; //固定为字符串“RIFF”
DWORDwbSize; //波形块的大小
DWORDwftype; //wav文件标志,固定为字符串“WAVE”
DWORDftype; //固定为字符串“fmt”
DWORDBlockSize; //格式块的大小
WORDwFormatTag; //记录波形编码格式。
为WAVE_FORMAT_PCM
WORDnChannels; //记录波形文件数据中的通道数
DWORDnSamplesPerSec;//记录波形文件的采样率
DWORDnAvgBytesPerSec;//平均每秒波形音频数据所需要的字节数
DWORDnBlockAlign; //记录一个采样所需要的字节数
WORDwBitsPerSample; //每个采样的位数
DWORDdataflag; //固定为字符串“data”
DWORDfSize; //波形文件大小
}PCMWAVEFORMAT;
BMP文件开始通常依次是14字节的文件头,40字节的位图信息,颜色表(真彩位图没有),最后是图像数据,对于用到调色板的位图,实际的图象数据ImageDate为该象素的颜色在调色板中的索引值;对于真彩色图,图象数据则为实际的R、G、B值。
位图数据每一行的字节数必须为4的整倍数,如果不是,则需要补齐;位图文件中的数据是从下到上(而不是从上到下)、从左到右方式存储的。
图像数据或者不压缩,或者使用RLE压缩。
文件头如下:
typedefstructtagBITMAPFILEHEADER{
WORDbftype;//固定为字符串“BM”
DWORDbfsize;//字节为单位的位图文件大小
WORDbfReserved1;//位图文件保留字,必须为0
WORDbfReserved2;//位图文件保留字,必须为0
DWORDbfoffBits;//指出图像数据针对文件头的偏移量
}BITMAPFILEHEADER;
typedefstructtagBITMAPINFOHEADER
{
DWORDbiSize;//本结构的长度,为40
LONGbiWidth;//图象的宽度,单位是象素
LONGbiHeight;//图象的高度,单位是象素
WORDbiPlanes;//必须是1
WORDbiBitCount;
//表示颜色时要用到的位数,1(单色),4(16色),8(256色),24(真彩色)
DWORDbiCompression;
//指定位图是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS等,BI_RGB表示不压缩
DWORDbiSizeImage;
//实际的位图数据占用的字节数,即biSizeImage=biWidth’×biHeight,biWidth’是biWidth按照4的整倍数调整后的结果
LONGbiXPelsPerMeter;//目标设备的水平分辨率,单位是每米的象素个数
LONGbiYPelsPerMeter;//目标设备的垂直分辨率,单位是每米的象素个数
DWORDbiClrUsed;//位图实际用到的颜色数,0表示颜色数为2biBitCount
DWORDbiClrImportant;//位图中重要的颜色数,0表示所有颜色都重要
}BITMAPINFOHEADER;
调色板Palette针对的是需要调色板的位图,即单色、16色和256色位图。
对于不以调色板方式存储的位图,则无此项信息。
调色板是一个数组,共有biClrUsed个元素(如果该值为0,则有2biBitCount个元素)。
数组中每个元素是一个RGBQUAD结构体,长度为4个字节,定义为:
typedefstructtagRGBQUAD
{
BYTErgbBlue;//蓝色分量
BYTErgbGreen;//绿色分量
BYTErgbRed;//红色分量
BYTErgbReserved;//保留值
}RGBQUAD;
6.2WINDOWS位图
WINSOWS位图编程的方法主要分为设备相关位图与设备无关位图。
DDB设备相关位图由MFC中CBitmap类表示,从应用程序的资源里获得完全依赖于设备的数据结构,很方便,但是局限性大。
DIB设备无关位图拥有位图的所有信息,此格式为所有位图文件所包含,也被WIN32API所支持,比GDI位图有更多的编程优势。
例:
DDB位图的显示
voidCGDIbmpView:
:
OnDraw(CDC*pDC)
{
CGDIbmpDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
CBitmapbm;
CDCdcMem;
bm.LoadBitmap(IDB_BITMAP2);
dcMem.CreateCompatibleDC(pDC);
dcMem.SelectObject(&bm);
pDC->BitBlt(20,20,400,600,&dcMem,0,0,SRCCOPY);
}
VisualC++MFC中没有提供一个专门的类来处理DIB位图,因此,为了方便地使用位图文件,一般派生一个CDib类。
最简单的如下所示:
classCDib
{
public:
CDib();
~CDib();
BOOLLoad(constchar*);//用来载入一个BMP文件
BOOLSave(constchar*);
BOOLDraw(CDC*,intnX=0,intnY=0,intnWidth=-1,intnHeight=-1,intmode=SRCCOPY);//在相应的设备中绘制
BOOLSetPalette(CDC*);//根据图象的调色板信息设定当前调色板
private:
CPalettem_Palette;
unsignedchar*m_pDib,*m_pDibBits;//m_pDib指向图象文件中从文件头以后的所有信息,包括图象信息、调色板、图象数据;载入文件的时候分配空间,析构函数中释放空间。
DWORDm_dwDibSize;
BITMAPINFOHEADER*m_pBIH;//指向信息头的指针
RGBQUAD*m_pPalette;//指向图象调色板的指针
intm_nPaletteEntries;
};
6.3媒体控制接口MCI
MCI(MediaControlInterface,媒体控制接口)向Windows程序提供了在高层次上控制媒体设备接口的能力。
程序不必关心具体设备,就可以对激光唱机(CD)、视盘机、波形音频设备、视频播放设备和MIDI设备等媒体设备进行控制。
核心是用于解释和执行MCI命令的MCI设备驱动程序。
简单设备:
如激光唱机等在播放时不要求数据文件。
复合设备:
如MIDI以及波形音响设备在播放的时候需要数据文件。
为了唯一地区分MCI驱动程序,MCI引入设备名,放在SYSTEM.INI文件的[MCI]段中。
设备类型和设备名是不同的概念。
设备类型是指响应一组共用命令的一类MCI设备,而设备名则是某一个MCI设备的名字。
[mci]
cdaudio=mcicda.drv
sequencer=mciseq.drv
waveaudio=mciwave.drv
avivideo=mciavi.drv
videodisc=mcipionr.drv
MCI编程接口可以利用近似英语的句法与MCI设备通信,被称为串方式。
有以下2个API:
BOOLmciExecute(lpstrCommand)
MCIERRORmciSendString(lpszCommand,lpszReturnString,
cchReturn,hwndCallback)
第一个参数指向以NULL结尾的MCI命令字符串,若成功则返回0,否则返回错误码BOOLmciGetErrorString(dwError,lpstrBuffer,wLength)
第一个参数为错误码。
第二个参数指向系统返回的错误描述文字串的缓存。
第三个参数指定缓存的长度。
函数调用成功返回TRUE,否则返回FALSE。
例如:
我们用“opencdaudio”串打开CD驱动器准备读取
charbuf[50];
MCIERRORmciError;
mciError=mciSendString(“opencdaudio”,buf,strlen(buf),NULL);
if(mciError)
{
mciGetErrorString(mciError,buf,strlen(buf));
AfxMessageBox(buf);
return;
}
MCI最常用的另一种方式是消息方式,即发送WINDOWS消息,传递相应的数据结构通知设备进行操作。
MCIERRORmciSendCommand(
MCIDEVICEIDIDDevice,//设备的ID,在打开设备时不用该参数
UINTuMsg,//命令消息
DWORDdwCommand,//命令消息的标志
DWORDdwParam//指向包含命令消息参数的结构
);//若成功则返回0,否则返回错误码
MCI的消息和命令有很多,下表显示了主要的指令。
1.波形音频
波形音频由于播放对象和需求的效果不同主要有以下四种操作方式
◆MessageBeep函数
◆PlaySound和sndPlaySound函数
◆MCI调用
◆Wave低级设备函数
第一种方式使用BOOLMessageBeep(UINTnType)函数直接播放一个声音,但是播放的音频文件都是预先被系统定义好的,因此发出的声音没有太多的变化。
例如:
MessageBeep(MB_OK);播放系统指定的ding.wav文件
MessageBeep(0xFFFFFFFF);使用PC扬声器发出嘟嘟的声音
第二种方式可以指定音频文件直接播放,使用函数
BOOLPlaySound(
LPCSTRpszSound,//声音资源的来源
HMODULEhmod,//装载资源的可执行文件句柄
DWORDfdwSound)//播放声音的标识和播放方式
例如:
PlaySound(“d:
\\ding.wav”,NULL,SND_FILENAME|
SND_ASYNC);
其中标志SND_FILENAME表示参数pszSound是音频文件名,还可以是SND_MEMORY(音频文件的内存指针)SND_RESOURCE(资源标志符)SND_ALIAS(定义过的系统声音)。
标志SND_ASYNC表示函数播放后立即返回,可以通过参数pszSound传递NULL终止正在播放的声音。
第三种方式就是使用MCI接口,可以实现更多的控制功能。
下面是几个常用的步骤和使用消息传送的方式:
①打开波形音频
WORDm_wDeviceID;//MCI设备名
CStringFilename;//波形文件名
…
MCI_OPEN_PARMSOpenParms;//MCI设备打开参数
OpenParms.lpstrDeviceType=“waveaudio”;//设备种类
OpenParms.lpstrElementName=Filename;
If(mciSendCommand(0,MCI_OPEN,MCI_OPEN_ELEMENT
|MCI_OPEN_TYPE,(DWORD)(LPVOID)&OpenParms))
returnFALSE;
m_wDeviceID=OpenParms.wDeviceID;
…
②播放波形音频
MCI_PLAY_PARMSPlayParms;//播放参数
mciSendCommand(m_wDeviceID,MCI_SEEK,
MCI_SEEK_TO_START,NULL);
//将播放指针定位在波形文件的开始
If(mciSendCommand(0,MCI_PLAY,MCI_NOTIFY,
(DWORD)(LPVOID)&PlayParms))
returnFALSE;
Else
returnTURE;
…
③关闭波形音频设备
mciSendCommand(m_wDeviceID,MCI_STOP,
MCI_WAIT,NULL);
//先停止播放当前的声音
mciSendCommand(m_wDeviceID,MCI_CLOSE,
MCI_NOTIFY,NULL);
//关闭设备
④获取波形音频参数
DWORDSampleRate;//采样率
MCI_STATUS_PARAMSStatusParms;//状态参数
StatusParms.dwItems=MCI_WAVE_STATUS_SAMPLESPERSEC;
//dwItems设置需要获得参数的信息标志
If(mciSendCommand(m_wDeviceID,MCI_STATUS,MCI_WAIT|
MCI_STATUS_ITEM,(DWORD)(LPVOID)&StatusParms))
return-1;
SampleRate=StatusParms.dwReturn;
//结果返回到dwReturn成员中
MCI_STATUS_PARAMS参数是重要参数,在它的属性dwItems填入需求的参数宏,属性dwReturn就会返回相应的值。
⑤设置波形音频参数
intnChannels=2;
MCI_WAVE_SET_PARAMSSetParms;//设置参数对象
SetParms.nChannels=nChannels;//设置声道数
(mciSendCommand(m_wDeviceID,MCI_SET,MCI_WAIT|
MCI_WAVE_SET_CHANNELS,(DWORD)(LPVOID)&SetParms))
对应不同的音频设备,设置的参数对象是不同的,对象中的属性根据不用的设备也有所不同。
比如MIDI的参数对象就是MCI_SEQ_SET_PARAMS。
⑥定位播放位置
BOOLSeekTo(intnMinute,intnSecond)
{MCI_SEEK_PARAMSSeekParms;
SeekParms.dwTo=(Min*60+Sec)*1000;
mciSendCommand(m_wDeviceID,MCI_PAUSE,0,NULL);
If(mciSendCommand(m_wDeviceID,MCI_SEEK,MCI_TO|
MCI_WAIT,(DWORD)(LPVOID)&SeekParms))
returnFALSE;
}
⑦取得当前位置
MCI_STATUS_PARMSStatusParms;
StatusParms.dwItem=MCI_STATUS_POSITION;
mciSendCommand(m_wDeviceID,MCI_STATUS,MCI_WAIT|MCI_STATUS_ITEM,(DWORD)(LPVOID)&StatusParms);
DWORDdwPos=StatusParms.dwReturn;
intMin=StatusParms.dwReturn/1000/60;//分
intSec=(StatusParms.dwReturn-min*60000)/1000;//秒
intFram=StatusParms.dwReturn-(min*60+sec)*1000;//毫秒
第四种方式是使用Wave低级设备函数,这个方式相对来说就比较复杂,需要编写很多的代码,但是也能更好的控制产生的声音。
比如调整播放音频的音量、音速和音调等。
低级波形函数播放声音时。
必须先将声音载入内存中,设置内存缓冲区。
waveOutOpen打开音频输入设备
waveInOpen为录制打开指定的输入设备
waveOutSetVolume设置音频输出设备的音量
2.MIDI音频
MIDI音频也采用MCI接口进行控制。
操作方式与WAVE的基本相同,只是在某些参数上有少许不同,比如在打开设备的时候,设备打开参数类型发生改变OpenParms.lpstrDeviceType=(LPCSTR)MCI_DEVTYPE_SEQUENCER。
3.CD音频
同样的,CD音频使用MCI也只是打开参数类型发生改变
OpenParms.lpstrDeviceType=(LPCSTR)MCI_DEVTYPE_CD_AUDIO;此外,它不需要指定文件;所获取的一些参数如音轨也是前面的2种音频不具有的,但是需要依靠某种转化方式得到。
4.视频
视频设备会用到一些音频设备所没有的MCI消息,比如
MCI_STEP跳过数字视频文件中的指定数目的帧
MCI_PUT将视频窗口置于父窗口中
MCI_WHERE确定视频的尺寸和位置
处理数字视频一般用专用的参数结构取代通常的MCI参数结构,例如:
MCI_OPEN_PARMS在这用MCI_DGV_OPEN_PARMS取代。
typedefstruct{
DWORDdwCallback;
UINTwDeviceID;
LPSTRlpstrDeviceType;//设备种类
LPSTRlpstrElementName;
LPSTRlpstrAlias;
DWORDdwStyle;//视频输出窗口的风格
HWNDhWndParent;//视频输出窗口的窗口句柄
}MCI_DGV_OPEN_PARMS
①打开播放数字视频的设备
WORDm_wDeviceID;//MCI设备名
…
MCI_DGV_OPEN_PARMSOpenParms;//MCI设备打开参数
OpenParms.lpstrDeviceType=“avivideo”;
OpenParms.lpstrElementName=(LPSTR)Filename.GetBuffer(0);
OpenParms.hWndParent=pWnd->m_hwnd;//将要播放视频的主窗口
OpenParms.dwStyle=WS_CHILD|WS_VISIBLE;//窗口属性
If(mciSendCommand(0,MCI_OPEN,MCI_WAIT|MCI_OPEN_TYPE
|MCI_OPEN_ELEMENT|MCI_DGV_OPEN_WS|
MCI_DGV_OPEN_PARENT,(DWORD)(LPVOID)&OpenParms))
returnFALSE;
m_wDeviceID=OpenParms.wDeviceID;
②设置数字视频的播放
MCI_DGV_SET_PARMSSetParms;
SetParms.dwAudio=MCI_SET_AUDIO_ALL;
DWORDdwFlags=MCI_SET_AUDIO;
If(bSound)
dwFlags|=MCI_SET_ON;
ElsedwFlags|=MCI_SET_OFF;(是否播放声音)
mciSendCommand(m_wDeviceID,MCI_SET,dwFlags,
(DWORD)(LPVOID)&SetParms);
③播放数字视频
MCI_DGV_PLAY_PARMSPlayParms;
PlayParms.dwCallback=NULL;
PlayParms.dwFrom=GetFrames();
If(mciSendCommand(m_wDeviceID,MCI_PLAY,MCI_FROM,
(DWORD)(LPVOID)&PlayParms))
returnFALSE;
m_bPaused=FALSE;//暂停标志为假
M_bPlaying=TRUE;//播放标志为真
注:
这里可以设置时间格式为帧MCI_FORMAT_FRAMES,使用参数MCI_STATUS_POSITION返回的就是帧数
③关闭数字视频
mciSendCommand(m_wDeviceID,MCI_STOP,
MCI_WAIT,NULL);
//先停止播放
mciSendCommand(m_wDeviceID,MCI_CLOSE,
MCI_NOTIFY,NULL);
//关闭设备
5.通用多媒体控件
现在有多种现成的多媒体控件供编程人员使用,利用这些控件,程序员可以用很小的代码获得更好的多媒体播放工具。
其中有两个控件可以对付多种媒体的播放。
⏹MicrosoftMultimediaControl该控件可以控制所有MCI注册的媒体的播放,它的界面就是一组播放按钮。
⏹ActiveMovieControl该控件可以很方便的将微软的媒体播放器嵌入到你的程序中,由于微软的WindowsMediaPlayer就是基于这个控件的,所以,嵌入的播放器样子很象媒体播放器,而且功能非常强大,并支持微软的流媒体,包括在网络上的实时收听和收看。
6.4OPENGL编程接口
OpenGL实际上是一种图形与硬件的接口。
它包括了100多个图形函数,开发者可以用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多媒体 编程 基础
![提示](https://static.bingdoc.com/images/bang_tan.gif)