PCM数据合成WAV文件

原创 2012年03月21日 11:00:01

由于需要解码后的裸数据保存下来看看效果,故需要将数据合成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);
}


相关文章推荐

wav与pcm数据

参考下这个 WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource InterchangeFileFormat的缩写,每个WAVE文件的头四个字节...

PCM格式保存为wav

HANDLE hFile; WAVE_HEADER wh; wh.szRiff = 'FFIR'; wh.szWave = 'EVAW'; wh.szFmt = ' tmf'; wh.Fm...
  • Sidyhe
  • Sidyhe
  • 2013年09月03日 09:23
  • 2161

嵌入式 wave文件(*.wav)格式、PCM数据格式收藏

1. 音频简介   经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等. 44100HZ 16bit stereo: 每秒钟有 441...
  • skdkjxy
  • skdkjxy
  • 2013年12月02日 14:56
  • 943

wave文件(*.wav)格式、PCM数据格式

 1. 音频简介 经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等.44100HZ 16bit stereo: 每秒钟有 44100 次采...

科大讯飞语音合成,pcm转wav

科大讯飞语音合成文件,pcm转wav

讯飞录音,把几个pcm合成为wav

由于讯飞录音是不能把一段很长的话录音出来,只能是一段一段的录,所以要把录出来的pcm数据合成wav文件,录音的采样率是8k, 比特率是16bit,双声道,合并的代码如下: public stat...

C#实现线性PCM祼数据加WAV头

  • 2017年06月14日 19:24
  • 8KB
  • 下载

二.PCM(44字节)的Wav文件头及其相关的编程方法

本文就经常见的一种格式PCM(44字节)的Wav文件头进行分析 一.解析文件头 表1 8KHz采样、16比特量化的线性PCM语音信号的WAVE文件头格式表(共44字节) 偏移地址 字节数 数据类...
  • xsjm206
  • xsjm206
  • 2011年08月28日 22:58
  • 6077

WAV(PCM)文件格式分析.doc

  • 2009年01月13日 18:21
  • 45KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:PCM数据合成WAV文件
举报原因:
原因补充:

(最多只允许输入30个字)