由于需要解码后的裸数据保存下来看看效果,故需要将数据合成WAV文件
ypedef struct
{
unsigned short format_tag;
unsigned short channels; /* 1 = mono, 2 = stereo */
unsigned long samplerate; /* typically: 44100, 32000, 22050, 11025 or 8000*/
unsigned long bytes_per_second; /* SamplesPerSec * BlockAlign*/
unsigned short blockalign; /* Channels * (BitsPerSample / 8)*/
unsigned short bits_per_sample; /* 16 or 8 */
} WAVEAUDIOFORMAT;
typedef struct
{
char info[4];
unsigned long length;
} RIFF_CHUNK;
void MuxWAV(LPCTSTR lpPCMFile, LPCTSTR lpDestWavFile, WORD wSampleBits, WORD wChannels, WORD wSamplerate)
{
CFile FSource;
BOOL bResult = FSource.Open(lpPCMFile, CFile::modeNoTruncate|CFile::modeRead|CFile::shareExclusive);
if(bResult == FALSE) return;
CFile FDest;
bResult = FDest.Open(lpDestWavFile, CFile::modeCreate|CFile::modeWrite);
if(bResult == FALSE)
{
FSource.Close();
return;
}
char* pTempData = new char[10*1024*1024];
WAVEAUDIOFORMAT format;
format.format_tag = 1;
format.channels = wChannels;
format.samplerate = wSamplerate;
format.bits_per_sample = wSampleBits;
format.blockalign = format.channels * (format.bits_per_sample/8);
format.bytes_per_second = format.samplerate * format.blockalign;
FDest.Write("RIFF\0\0\0\0WAVEfmt ", 16);
int length = 16;
FDest.Write(&length, 1*sizeof(long));
FDest.Write(&format, sizeof(format));
FDest.Write("data\0\0\0\0", sizeof(char)*8); /* Write data chunk */
while(true)
{
DWORD dwReadLength = FSource.ReadHuge(pTempData, 10*1024*1024);
if(dwReadLength == 0) break;
FDest.WriteHuge(pTempData, dwReadLength);
}
FSource.Close();
DWORD dwLength = FDest.GetLength();
long RiffLen = dwLength - 8;
long DataLen = dwLength - 44;
FDest.Seek(4, CFile::begin);
FDest.Write(&RiffLen, sizeof(long));
FDest.Seek(40, CFile::begin);
FDest.Write(&DataLen, sizeof(long));
FDest.Seek(0, CFile::end);
FDest.Close();
}
顺便提供提取WAV文件中的PCM数据函数
void ExtraWAV(CString& strPath)
{
HANDLE hRead = ::CreateFile(strPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(!hRead) return;
const int MBSize = 1024;
byte buffer[MBSize] = {0};
DWORD dwReadBytes = 0;
DWORD dwFileSize = 0;
GetFileSize(hRead, &dwFileSize);
DWORD dwReadOffset = 0;
int err = 0;
FMT_BLOCK waveBlock;
RIFF_HEADER riffHeader;
ReadFile(hRead, &riffHeader, sizeof(riffHeader), &dwReadBytes, NULL);
if(dwReadBytes != sizeof(riffHeader)) return;
ReadFile(hRead, &waveBlock, sizeof(waveBlock), &dwReadBytes, NULL);
if(dwReadBytes != sizeof(waveBlock)) return;
dwReadOffset += sizeof(RIFF_HEADER) + sizeof(FMT_BLOCK);
if(waveBlock.dwFmtSize == 0x12)
{
ReadFile(hRead, buffer, 2, &dwReadBytes, NULL);
if(dwReadBytes != 2) return;
dwReadOffset += 2;
}
ReadFile(hRead, buffer, 4, &dwReadBytes, NULL);
if(dwReadBytes != 4) return;
dwReadOffset += sizeof(DWORD);
DWORD dwDataSize = 0;
ReadFile(hRead, &dwDataSize, sizeof(dwDataSize), &dwReadBytes, NULL);
if(dwReadBytes != sizeof(dwDataSize)) return;
dwReadOffset += sizeof(DWORD);
int nPos = strPath.ReverseFind('.');
CString strNewFile;
DWORD dwIndex = 0;
strNewFile = strPath.Left(nPos + 1) + _T("pcm");
while(1)
{
CFile file;
if(file.Open(strNewFile, CFile::modeRead))
{
dwIndex++ ;
strNewFile.Format(_T("%s~%d.pcm"), strPath.Left(nPos), dwIndex);
file.Close();
}
else
{
break;
}
}
HANDLE hWrite = ::CreateFile(strNewFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(!hWrite) return;
HANDLE hFileReadMapping = ::CreateFileMapping(hRead,NULL,PAGE_READONLY, 0, dwFileSize, NULL);
if(!hFileReadMapping)
err = GetLastError();
HANDLE hFileWriteMapping = ::CreateFileMapping(hWrite,NULL,PAGE_READWRITE, 0, dwDataSize, NULL);
if(!hFileWriteMapping)
err = GetLastError();
PBYTE pRead = (PBYTE)MapViewOfFile(hFileReadMapping, FILE_MAP_READ, 0, 0, dwFileSize);
if(!pRead)
err = GetLastError();
PBYTE pWrite = (PBYTE)MapViewOfFile(hFileWriteMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwDataSize);
if(!pWrite)
err = GetLastError();
memcpy(pWrite, pRead + dwReadOffset, dwDataSize);
UnmapViewOfFile(pRead);
UnmapViewOfFile(pWrite);
CloseHandle(hFileReadMapping);
CloseHandle(hFileWriteMapping);
CloseHandle(hRead);
CloseHandle(hWrite);
}