多媒体文件I/O

 多媒体文件I/O

多媒体文件I/O与普通文件I/O相似,但支持多媒体“RIFF”格式,并提供了缓冲和非缓冲文件I/O。

所有的多媒体文件I/O函数名前缀为mmio,消息名前缀为MMIO。

低级波形音频函数:

低级音频服务允许用户直接与音频设备驱动程序打交道,直接控制音频设备如波形,Midi的播放与记录,低级音频函数是一个设备无关接口。

低级音频函数前缀均为wave,按输入函数、输出函数区分为WaveIn××××和WaveOut××××。

波形音频的重放过程。

首先,我们要调用多媒体文件I/O函数mmIO××××( ),并根据多媒体文件I/O生成在wave重放中需要的结构和数据,并将这些结构和数据用waveOut××××( )函数重放。 用户可以根据加密的需要将wave文件篡改,去掉文件头和“fmt”块,只保留数据块。 或者将其压缩,只要重放时能在内存中还原出数据文件。并记得文件音频格式和大小,就能重放音频。

常用mmio函数及实现过程简介:

mmioOpen( )    打开一个RIFF文件

mmioDescend( )  进入块

mmioRead( );   该取RIFF文件

mmioAscend ( );  跳出块

mmioClose( );   关闭PIFF文件

对于块来说,进入块和跳出块是配对的。

读取WAV文件的读取过程:

mmioOpen( )   打开文件

   ↓

mmioDescend ("WAVE") 进入"fmt"块

   ↓

mmioRead( )     读取WAVE文件格式信息

   ↓

mmioAscend ( )    跳出"fmt"块

   ↓

mmioDescend ("data") 进入"data"块

   ↓

mmioRead( )     读取WAVE数据信息

   ↓

mmioClose( )     关闭文件。

输出WAV文件的过程:

WaveOutOpen ()打开一个输出设备

   ↓

WaveOutPrepareHeader()准备WAVE数据头。

   ↓

WaveOutWrite() 将数据写入设备并开始播放

   ↓

WaveOutReset() 停止播放并重置管理器

   ↓

WaveOutClose()并闭播放设备

   ↓

WaveOutUnpareHeader()清理用WaveOutPrepareHeader准备的Wave。

实例:

这个实例实现的功能是首先打开背景音乐,然后每五秒钟加入一段配音。背景音乐放完后将停止播放,大家可以听一下背景+配音+配音+……+配音产生的实际效果。为了实现这个功能,我们封装了一个类。大家可以在光盘上找到这两个文件“wavemix..h”和“wavemix.cpp” .

首先,我们看一下“wavmix.h”,这里定义了一个称为“mwave”的类,

其中成员函数有:构造、析构函数、open(打开文件)、play(播放文件)、Add(往缓冲中加混音文件)、Stop(停止播出)、close(关闭输出设备,类重新初始化)。

现在我们照前面方法建一个基于对话框的程序,在“File View”中加入上述两个文件。打开“WavemixDlg.h”,在前面加上“#include "wavemix.h"”,

在类class cWavemixDlg中加入私有数据“MWAVE mWave”,在类“cwavemixDlg”中加入成员OnlnitDialog( )和OnTime(),,

在此函数中加入一个定时器,打开并播放背景音乐。在定时器的向应过程OnTime()中加入函数mwave.Add("2.waw".)使之每五秒钟向缓冲加入一个配音。编译并运行之。

源程序分析

// wavemix.h : main header file for the WAVEMIX application
//
#if !defined(AFX_WAVEMIX_H__54F4AF66_CE37_11D1_94F8_0000B431BBA1__INCLUDED_)
#define AFX_WAVEMIX_H__54F4AF66_CE37_11D1_94F8_0000B431BBA1__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h"// main symbols
/////////////////////////////////////////////
#include "windows.h"
#include "mmsystem.h"
#ifdef WIN32
#define WAVDATABYTE
#else
#define WAVDATABYTE _huge
#define WAVEFORMATEX PCMWAVEFORMAT
#endif

#ifdef WIN32
#define WAV16DATAWORD
#else
#define WAV16DATAWORD _huge
#endif

class MWAVE
{
private:
BOOL OpenFlage;
DWORDDataSize;
HGLOBALhData;
WAVDATA*lpData;

PCMWAVEFORMAT pFormat;
WAVEHDRWaveHead;
HWAVEOUT hWaveOut;

public:
MWAVE(){memset(this,0,sizeof(MWAVE));};
~MWAVE(){Close();};
int Open(char*);//打开一个WAV文件
int Play(HWND);//播放一个WAV文件
int Add(char*);//往正在播放的WAV设备中添加WAV                                       文件
int Stop();//停止播放
int Close();//关闭设备
};

#endif // !defined(AFX_WAVEMIX_H__54F4AF66_CE37_11D1_94F8_0000B431BBA1__INCLUDED_)

// wavemix.cpp:Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "wavemix.h"
#include "wavemixDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////////////////////
// wavemix Class
//////////////////////////////////////

int MWAVE::Open(char* name)
{
HMMIO hMmio;
MMCKINFO pinfo;
MMCKINFO cinfo;

if(hMmio)Close();

//打开WAV文件,返回一个HMMIO句柄
hMmio=mmioOpen(name,NULL,MMIO_READ);
if(!hMmio)return FALSE;
OpenFlage=1;

//查找父块"wave";
pinfo.fccType=mmioFOURCC('W','A','V','E');
if(mmioDescend(hMmio,&pinfo,NULL,MMIO_FINDRIFF))goto FALSE_END;

//查找子块"fmt"  parent"riff";
cinfo.ckid=mmioFOURCC('f','m','t',' ');
if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
             goto FALSE_END;

mmioRead(hMmio,(LPSTR)&pFormat,sizeof(PCMWAVEFORMAT));//cinfo.cksize);
if(pFormat.wf.wFormatTag!=WAVE_FORMAT_PCM)
             goto FALSE_END;

//跳入块"FMT"
mmioAscend(hMmio,&cinfo,0);

//查找数据块
cinfo.ckid=mmioFOURCC('d','a','t','a');
if(mmioDescend(hMmio,&cinfo,&pinfo,MMIO_FINDCHUNK))
             goto FALSE_END;
DataSize=cinfo.cksize;

//读取数据
hData=GlobalAlloc(GMEM_MOVEABLE
                         | GMEM_SHARE,DataSize);
lpData=(WAVDATA*)GlobalLock(hData);
if( !hData || !lpData ) goto FALSE_END;
if(mmioRead(hMmio,(HPSTR)lpData,DataSize)
                                        !=(LRESULT)DataSize)
             goto FALSE_END;

//close and return
mmioClose(hMmio,MMIO_FHOPEN);
return TRUE;

FALSE_END:
if(hMmio)mmioClose(hMmio,MMIO_FHOPEN);
if(lpData)LocalUnlock(hData);
if(hData)GlobalFree(hData);
memset(this,0,sizeof(MWAVE));
return 0;
}

int MWAVE::Play(HWND hP)
{
if(!OpenFlage)return FALSE;

//检测系统播放功能
if(waveOutOpen(NULL,WAVE_MAPPER,
                       (WAVEFORMATEX*)&pFormat,NULL,
                        NULL,WAVE_FORMAT_QUERY))
            return Close();

if(waveOutOpen(&hWaveOut,WAVE_MAPPER,
                  ( WAVEFORMATEX*)&pFormat,(DWORD)hP,
                                 0,CALLBACK_WINDOW))
            return Close();

WaveHead.lpData=(LPSTR)lpData;
WaveHead.dwBufferLength=DataSize;
WaveHead.dwFlags=0L;
WaveHead.dwLoops=0L;

//往WAV设备中添加数据

if(waveOutPrepareHeader(hWaveOut,&WaveHead,
         sizeof(WAVEHDR)))

           return Close();

if(waveOutWrite(hWaveOut,&WaveHead,sizeof(WAVEHDR)))
           return Close();

return TRUE;
}

//#define min(a, b)  (((a) < (b)) ? (a) : (b))

int MWAVE::Add(char* name)
{
register int x;
if(!OpenFlage)return Open(name);

MWAVE wav;
if(!wav.Open(name))return FALSE;

MMTIME time;
//获得WAV文件当前播放位置

time.wType=TIME_BYTES;

if(waveOutGetPosition(hWaveOut,&time,sizeof(MMTIME)))
time.u.cb=0;
DWORD start=((time.u.cb>>1)<<1);
DWORD end=min(DataSize_start,wav.DataSize);

register WAVDATA* lpd=lpData+start;
for(register DWORD i=0;i<end;i++)
{


//将两组WAV文件数据相加,并检测数据大小是否合法,如果//数据大小越界,则分别取最大值和最小值

x=(((*(lpd+i))+(*(wav.lpData+i))))_128;


if(x<0)x=0;
  if(x>255)x=255;
*(lpd+i)=(BYTE)(x);
}

return TRUE;
}

int MWAVE::Stop()
{return !waveOutReset(hWaveOut);}

int MWAVE::Close()
{
if(hWaveOut)
{
waveOutReset(hWaveOut);
waveOutClose(hWaveOut);
waveOutUnprepareHeader(hWaveOut,&WaveHead,
                                             sizeof(WAVEHDR));
}
if(lpData)LocalUnlock(hData);
if(hData)GlobalFree(hData);
memset(this,0,sizeof(MWAVE));
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值