文件结构
RIFF文件由文件头、数据类型标识及若干块组成。块(chunk)是RIFF文件的基本结构,每个块都包括如下三个域:
1、用于标识块类型的4字符代码,如’RIFF’、’LIST’和’fmt
’、’data’等;
2、数据块大小的字节数
3、数据域本身
RIFF文件中的块是可以嵌套的,块的数据域可含若干子块,子块又可含孙块。例如,RIFF文件本身就是一个RIFF块,其数据域可以是WAV子块或AVI子块,而WAV子块又包含格式块('fmt
‘)和数据块('data’),AVI文件的AVI子块,包含格式列表块(’LIST’)、数据列表块(’LIST’)和可选的索引块(’ind1’),……。
RIFF文件具有相同的结构:
’RIFF’……
例如,WAV文件的结构为:
’RIFF’’WAVE’
而AVI文件的结构为:
’RIFF’’AVI
’[]
从WAV文件的结构可知,有两个数据至关重要
1、文件大小:标识文件的长度
2、数据块大小:标识WAV数据块大小
如何要将两个WAV文件合并,不同的部分只有数据块,即只需要将第二个文件的数据块COPY到第一个文件末尾,同时将第一个文件的文件大小、数据块大小两个数据与第二个文件的数据块大小相加,生成第三个文件即为合成的文件
知道了上述道理、简单实现如下:
CString strName1,strName2,strName3;
GetDlgItem(IDC_EDIT1)->GetWindowText(strName1);
GetDlgItem(IDC_EDIT2)->GetWindowText(strName2);
strName3 =
strName1.Left(strName1.GetLength()-4)+_T("bak.wav");
if
(!CopyFile(strName1,strName3,FALSE))//copy第一个文件到第三个文件
{
AfxMessageBox("copy file fail");
}
CFile file1;
CFile file2;
CFile file3;
file2.Open(strName2,CFile::modeRead);
DWORD dwLength;
file2.Seek(40,CFile::begin);
file2.Read(&dwLength,sizeof(DWORD));//读取第二个文件的数据块长度
file1.Open(strName1,CFile::modeRead);
file3.Open(strName3,CFile::modeReadWrite);
DWORD dwFileLength,dwDataLength;
file1.Seek(4,CFile::begin);
file1.Read(&dwFileLength,sizeof(DWORD));//获取第一个文件的大小
file1.Seek(40,CFile::begin);
file1.Read(&dwDataLength,sizeof(DWORD));//获取第一个文件的数据块大小
file3.Seek(4,CFile::begin);
dwFileLength +=dwLength;
dwDataLength +=dwLength;
file3.Write(&dwFileLength,sizeof(DWORD));//写入新得文件大小
file3.Seek(40,CFile::begin);
file3.Write(&dwDataLength,sizeof(DWORD));//写入新的数据块大小
file3.SeekToEnd();
BYTE buffer[100];
memset(buffer,0,sizeof(buffer));
while (TRUE)
{
int nLength =
file2.Read(buffer,sizeof(buffer));//读取第二个文件数据块
file3.Write(buffer,nLength);//写入第三个文件
if (nLength <
sizeof(buffer))
{
break;
}
}
file1.Close();
file2.Close();
file3.Close();
在visual c++ 6.0+winxp下测试通过,
目前只是针对简单固定的wav格式进行处理,未考虑WAV文件格式块与数据块之间存在其他块的可能,如果有各位有更好的不用mmioOpen(strFilePath,
NULL, MMIO_READ);的方法,请告知