//////////////////////////////////////////////////////////////////////////////////////
// by LZJ
// 2003.8
//
#include "stdafx.h"
#include <Mmsystem.h>
#include <dsound.h>
#include <math.h>
#include "WavChart.h"
#include "ProgDlg.h"
//-------------------------------------CWaveChannel-------------------------------------
IMPLEMENT_SERIAL(CWavChannel, CObject, 0)
CWavChannel::CWavChannel()
{
m_sLeftChannelData = 0;
m_sRightChannelData = 0;
}
void CWavChannel:
perator= ( const CWavChannel&
src )
{
m_sLeftChannelData = src.m_sLeftChannelData;
m_sRightChannelData = src.m_sRightChannelData;
}
void CWavChannel::Serialize( CArchive&
ar )
{
WORD wVer = 0;
if (ar.IsStoring())
{
ar << wVer;
ar << m_sLeftChannelData;
ar << m_sRightChannelData;
}
else
{
ar >> wVer;
ar >> m_sLeftChannelData;
ar >> m_sRightChannelData;
}
}
//-------------------------------------CWavFileInfo-------------------------------------
IMPLEMENT_SERIAL(CWavFileInfo,CObject,0)
CWavFileInfo::CWavFileInfo()
{
m_dwPosition = 0;
}
CWavFileInfo::~CWavFileInfo()
{
delete m_fFile;
}
void CWavFileInfo:
perator= ( const CWavFileInfo&
src )
{
m_dwPosition = src.m_dwPosition;
memcpy(m_fFile,src.m_fFile,sizeof(*m_fFile));
}
void CWavFileInfo::Serialize( CArchive&
ar )
{
WORD wVer = 0;
if (ar.IsStoring())
{
ar << wVer;
ar << m_dwPosition;
}
else
{
ar >> wVer;
ar >> m_dwPosition;
}
}
//-------------------------------------CWavFileRelate-------------------------------------
IMPLEMENT_SERIAL(CWavFileRelate,CObject,0)
CWavFileRelate::CWavFileRelate()
{
m_dwComposeFileId = 0;
m_dwFileInfoId = 0;
}
void CWavFileRelate:
perator= ( const CWavFileRelate&
src )
{
m_dwComposeFileId = src.m_dwComposeFileId;
m_dwFileInfoId = src.m_dwFileInfoId;
}
void CWavFileRelate::Serialize( CArchive&
ar )
{
WORD wVer = 0;
if (ar.IsStoring())
{
ar << wVer;
ar << m_dwComposeFileId;
ar << m_dwFileInfoId;
}
else
{
ar >> wVer;
ar >> m_dwComposeFileId;
ar >> m_dwFileInfoId;
}
}
//-------------------------------------CWavComposeInfo----------------------------------
IMPLEMENT_SERIAL(CWavComposeInfo,CObject,0)
CWavComposeInfo::CWavComposeInfo()
{
m_bLeft = FALSE;
m_bRight = FALSE;
m_dbStoryIn = 0;
m_dbTrimIn = 0;
m_dbTrimOut = 0;
}
void CWavComposeInfo:
perator=(const CWavComposeInfo&
src)
{
m_bLeft = src.m_bLeft;
m_bRight = src.m_bRight;
m_dbStoryIn = src.m_dbStoryIn;
m_dbTrimIn = src.m_dbTrimIn;
m_dbTrimOut = src.m_dbTrimOut;
m_strFileName = src.m_strFileName;
}
void CWavComposeInfo::Serialize(CArchive&
ar)
{
WORD wVer = 0;
if (ar.IsStoring())
{
ar << wVer;
ar << m_strFileName;
ar << m_bLeft;
ar << m_bRight;
ar << m_dbStoryIn;
ar << m_dbTrimIn;
ar << m_dbTrimOut;
}
else
{
ar >> wVer;
ar >> m_strFileName;
ar >> m_bLeft;
ar >> m_bRight;
ar >> m_dbStoryIn;
ar >> m_dbTrimIn;
ar >> m_dbTrimOut;
}
}
//-------------------------------------CWavChart----------------------------------------
IMPLEMENT_SERIAL(CWavChart, CObject, 0)
CWavChart::CWavChart()
{
m_dwDataLength = 0;
m_dwMaxValue = 0;
m_dwPlayTime = 0;
m_dwPosition = 0;
m_dwSecondPerSample = 0;
m_dwSize = 0;
memset(&m_wftx, 0, sizeof(m_wftx));
}
void CWavChart:
perator= (const CWavChart&
src)
{
// free current members
m_dwSize = src.m_dwSize;
m_dwPosition = src.m_dwPosition;
m_dwDataLength = src.m_dwDataLength;
memcpy(&m_wftx, &src.m_wftx, sizeof(m_wftx));
m_dwPlayTime = src.m_dwPlayTime;
m_dwMaxValue = src.m_dwMaxValue;
m_dwSecondPerSample = src.m_dwSecondPerSample;
m_olData.DeleteAll();
POSITION pos = src.m_olData.GetHeadPosition();
while (pos != NULL)
{
CWavChannel *pCh = (CWavChannel*)src.m_olData.GetNext(pos);
CWavChannel *pNewCh = new CWavChannel;
*pNewCh = *pCh;
m_olData.AddTail(pNewCh);
}
}
void CWavChart::Serialize(CArchive&
ar)
{
WORD wVer = 0;
if (ar.IsStoring())
{
ar << wVer;
ar << m_dwMaxValue;
ar << m_dwSize;
ar << m_dwPosition;
ar << m_dwDataLength;
ar << m_dwSecondPerSample;
ar << m_dwPlayTime;
ar.Write(&m_wftx, sizeof(m_wftx));
}
else
{
ar >> wVer;
ASSERT(0 == wVer);
ar >> m_dwMaxValue;
ar >> m_dwSize;
ar >> m_dwPosition;
ar >> m_dwDataLength;
ar >> m_dwSecondPerSample;
ar >> m_dwPlayTime;
ar.Read(&m_wftx, sizeof(m_wftx));
}
m_olData.Serialize(ar);
}
BOOL CWavChart::OpenFile(LPCTSTR lpstrFileName)
{
ASSERT(lpstrFileName != NULL);
DWORD dwCurPosition = 0;
DWORD dwType;
DWORD dwLength;
short sValue;
CFile fFile;
CWavChannel *pwcWavChannel;
if (!fFile.Open(lpstrFileName,CFile::modeRead,NULL))
{
ASSERT(FALSE);
return FALSE;
}
VERIFY(fFile.Seek(4, CFile::begin
) > 0);
VERIFY(fFile.Read(&m_dwSize, 4) > 0);
//头文件分析
fFile.Seek(0, CFile::begin
);
while (dwCurPosition<m_dwSize)
{
fFile.Seek(dwCurPosition, CFile::begin
);
VERIFY(fFile.Read(&dwType, 4) > 0);
switch(dwType)
{
case mmioFOURCC('f','m','t',' '):
dwCurPosition+=4;
fFile.Seek(dwCurPosition,CFile::begin
);
VERIFY(fFile.Read(&dwLength,4) > 0);
dwCurPosition+=4;
fFile.Read(&m_wftx,dwLength);
break;
case mmioFOURCC('d','a','t','a'):
dwCurPosition+=4;
fFile.Seek(dwCurPosition,CFile::begin
);
VERIFY(fFile.Read(&m_dwDataLength,4) > 0);
m_dwPosition=dwCurPosition+4;
dwCurPosition = m_dwSize;
break;
}
dwCurPosition++;
}
m_dwMaxValue = 10000;
m_dwSecondPerSample = 40; //取样时间
if (m_wftx.nAvgBytesPerSec > 0)
m_dwPlayTime = m_dwDataLength/(m_wftx.nAvgBytesPerSec/1000);
//写入链表
m_olData.DeleteAll();
for (DWORD i=0;i<m_dwPlayTime;
i+=m_dwSecondPerSample)
{
pwcWavChannel = new CWavChannel;
if (i!=0) fFile.Seek(m_dwSecondPerSample*m_wftx.nAvgBytesPerSec/1000-4,CFile::current);
VERIFY(fFile.Read(&sValue,2) > 0);
pwcWavChannel->m_sLeftChannelData = sValue;
VERIFY(fFile.Read(&sValue,2) > 0);
pwcWavChannel->m_sRightChannelData = sValue;
m_olData.AddTail(pwcWavChannel);
}
fFile.Close();
return TRUE;
}
//波形图
BOOL CWavChart::Chart(CRect *pRect,CDC *pDC,double dbInTime,double dbOutTime,int iChannel,double dbTimeUnit)
{
ASSERT(pRect!=NULL &&
pDC!=NULL);
if (m_olData.GetCount() <= 0)
return FALSE;
short sValue;
DWORD dwValue;
CWavChannel *pwcWavChannel = NULL;
int iInTime = (int)(dbInTime*1000);
int iOutTime = (int)(dbOutTime*1000);
//DWORD dwMillSecondPerHP = (iOutTime-iInTime)/pRect->Width();
pDC->MoveTo(pRect->left,pRect->top+pRect->Height()/2);
// Goto head position
POSITION pos = m_olData.GetHeadPosition();
// Find the intime position
DWORD dwStartPosition = (DWORD)(iInTime/m_dwSecondPerSample);
ASSERT(dwStartPosition < (DWORD)m_olData.GetCount());
while (dwStartPosition>0)
{
m_olData.GetNext(pos);
dwStartPosition--;
}
ASSERT(pos != NULL);
DWORD dwCurPosition = 0;
float fListPosition = 0;
float fSecondStep = (float)(dbTimeUnit*40/m_dwSecondPerSample);
//start
float fPtStep = 1/fSecondStep;
int iPtSum = (int)(pRect->Width()/fPtStep);
float fDrawStart = (float)pRect->left;
while(iPtSum>0 &&
pos!=NULL)
{
fDrawStart += fPtStep;
pwcWavChannel = (CWavChannel*)m_olData.GetNext(pos);
if (iChannel==0)
{
sValue = pwcWavChannel->m_sLeftChannelData;
}
else
{
sValue = pwcWavChannel->m_sRightChannelData;
}
dwValue = (abs(sValue)*pRect->Height())/m_dwMaxValue;
if (sValue>=0)
{
pDC->LineTo((int)fDrawStart,pRect->top+pRect->Height()/2-dwValue);
}
else
{
pDC->LineTo((int)fDrawStart,pRect->top+pRect->Height()/2+dwValue);
}
iPtSum--;
}
//end
/*for (int i=0;i<pRect->Width();i++, fListPosition+=fSecondStep)
{
while (dwCurPosition<(DWORD)fListPosition &&
pos!=NULL)
{
m_olData.GetNext(pos);
dwCurPosition++;
}
if(dwCurPosition <= (DWORD)fListPosition)
{
if (pos!=NULL)
{
pwcWavChannel = (CWavChannel*)m_olData.GetNext(pos);
dwCurPosition++;
}
else
{
pwcWavChannel->m_sLeftChannelData = 0;
pwcWavChannel->m_sRightChannelData = 0;
}
}
if (iChannel==0)
{
sValue = pwcWavChannel->m_sLeftChannelData;
}
else
{
sValue = pwcWavChannel->m_sRightChannelData;
}
dwValue = (abs(sValue)*pRect->Height())/m_dwMaxValue;
if (sValue>=0)
{
pDC->LineTo(pRect->left+i,pRect->top+pRect->Height()/2-dwValue);
}
else
{
pDC->LineTo(pRect->left+i,pRect->top+pRect->Height()/2+dwValue);
}
}*/
return TRUE;
}
//wave合成
BOOL CWavChart::ComposeToFile(CMyObList *olComposeFile,LPCTSTR lpstrFileName)
{
do
uble dbDataLength = 0;
CWavComposeInfo *wci;
CFile fComposeFile;
//get max length;
POSITION pos = olComposeFile->GetHeadPosition();
ASSERT(olComposeFile->GetCount());
int iPosCount = olComposeFile->GetCount();
while (iPosCount>0)
{
wci = (CWavComposeInfo*)olComposeFile->GetNext(pos);
if (wci->m_dbStoryIn+wci->m_dbTrimOut-wci->m_dbTrimIn > dbDataLength)
dbDataLength = wci->m_dbStoryIn+wci->m_dbTrimOut-wci->m_dbTrimIn;
iPosCount--;
}
if (!fComposeFile.Open(lpstrFileName,CFile::modeCreate|CFile::modeReadWrite,NULL))
return FALSE;
//head PCWAVEFORMAT
WAVEFORMAT wf;
wf.nAvgBytesPerSec = 192000;
wf.nBlockAlign = 4;
wf.nChannels = 2;
wf.nSamplesPerSec = 48000;
wf.wFormatTag = WAVE_FORMAT_PCM;
PCMWAVEFORMAT pcmwf;
pcmwf.wBitsPerSample = 16;
pcmwf.wf = wf;
//Create basic wave file;
fComposeFile.SeekToEnd();
char headriff[] = {'R','I','F','F'};
fComposeFile.Write(headriff,4);
DWORD dwFileLength = 20+sizeof(PCMWAVEFORMAT)+(DWORD)(dbDataLength*192000);
fComposeFile.Write(&dwFileLength,4);
char headwave[] = {'W','A','V','E'};
fComposeFile.Write(headwave,4);
char headfmt[] = {'f','m','t',' '};
fComposeFile.Write(headfmt,4);
DWORD dwPCMWFSize = sizeof(PCMWAVEFORMAT);
fComposeFile.Write(&dwPCMWFSize,4);
fComposeFile.Write(&pcmwf,dwPCMWFSize);
char headdata[] = {'d','a','t','a'};
fComposeFile.Write(headdata,4);
DWORD dwDataLength = (DWORD)(dbDataLength*192000);
fComposeFile.Write(&dwDataLength,4);
DWORD dwFilePosLength = (DWORD)(dbDataLength*48000);
//进度条
CProgDlg ProgDlg;
ProgDlg.Create(_T("文件扫描"), _T("文件扫描进度..."), FALSE, NULL);
ProgDlg.SetRange(0,dwFilePosLength);
ProgDlg.SetPos(0);
DWORD sNull = 0;
for (DWORD i=0;i<dwFilePosLength;i++)
{
if(i>0 &&
i*100/dwFilePosLength>(i-1)*100/dwFilePosLength)
ProgDlg.SetPos(i);
fComposeFile.Write(&sNull,4);
}
//fComposeFile.SetLength(dwFileLength);
ProgDlg.Close();
pos = olComposeFile->GetHeadPosition();
DWORD dwCount = olComposeFile->GetCount();
DWORD dwOldCount = dwCount;
//Create olFileInfo,olFileRelate;
CMyObList olFileInfo;
CMyObList olFileRelate;
POSITION pFileInfo = olFileInfo.GetHeadPosition();
POSITION pFileRelate = olFileRelate.GetHeadPosition();
pos = olComposeFile->GetHeadPosition();
ProgDlg.Create(_T("音频合成"), _T("音频合成进度..."), FALSE, NULL);
ProgDlg.SetRange(0,dwFilePosLength);
ProgDlg.SetPos(0);
CWavFileRelate *wfrPre;
DWORD dwFileNum = 0;
for (i=0;i<dwCount;i++)
{
pos =olComposeFile->GetHeadPosition();
for (DWORD q=0;q<=i;q++)
wci = (CWavComposeInfo*)olComposeFile->GetNext(pos);
LPCTSTR strFileName = wci->m_strFileName;
pos = olComposeFile->GetHeadPosition();
BOOL bExist=FALSE;
for (DWORD j=0;j<i;j++)
{
wci = (CWavComposeInfo*)olComposeFile->GetNext(pos);
if (wci->m_strFileName == strFileName)
{
CWavFileRelate *wfrExist = new CWavFileRelate();
pFileRelate = olFileRelate.GetHeadPosition();
for (DWORD m=0;m<=j;m++)
{
wfrPre = (CWavFileRelate*)(olFileRelate.GetNext(pFileRelate));
}
wfrExist->m_dwComposeFileId = i;
wfrExist->m_dwFileInfoId = wfrPre->m_dwFileInfoId;
olFileRelate.AddTail(wfrExist);
bExist = TRUE;
break;
}
}
//the file not open
if (bExist==FALSE)
{
CFile *fFile = new CFile();
if (!fFile->Open(strFileName,CFile::modeRead,NULL))
return FALSE;
CWavFileInfo *wfiExist = new CWavFileInfo();
DWORD dwSize = 0;
DWORD dwCurPosition = 0;
DWORD dwType;
fFile->Seek(4, CFile::begin
);
fFile->Read(&dwSize, 4);
fFile->Seek(0, CFile::begin
);
while (dwCurPosition<dwSize)
{
fFile->Seek(dwCurPosition, CFile::begin
);
fFile->Read(&dwType, 4);
if (dwType == mmioFOURCC('d','a','t','a'))
{
fFile->Seek(4,CFile::current);
dwCurPosition += 8;
break;
}
dwCurPosition++;
}
wfiExist->m_fFile = fFile;
wfiExist->m_dwPosition = 0;
olFileInfo.AddTail(wfiExist);
CWavFileRelate *wfrExist = new CWavFileRelate();
wfrExist->m_dwComposeFileId = i;
wfrExist->m_dwFileInfoId = dwFileNum;
olFileRelate.AddTail(wfrExist);
dwFileNum++;
}
}
//compose wave
fComposeFile.Seek(28+sizeof(PCMWAVEFORMAT),CFile::begin
);
short sStoryLeft;
short sStoryRight;
short sTrimLeft;
short sTrimRight;
short sTotalTrimLeft = 0;
short sTotalTrimRight = 0;
CWavFileRelate *wfr;
CWavFileInfo *wfi;
POSITION pWfr,pWfi;
for (i=0;i<dwFilePosLength;i++)
{
if(i>0 &&
i*100/dwFilePosLength>(i-1)*100/dwFilePosLength)
ProgDlg.SetPos(i);
fComposeFile.Read(&sStoryLeft,2);
fComposeFile.Read(&sStoryRight,2);
sTotalTrimLeft = 0;
sTotalTrimRight = 0;
pos = olComposeFile->GetHeadPosition();
for (DWORD j=0;j<dwCount;j++)
{
wci = (CWavComposeInfo*)olComposeFile->GetNext(pos);
pWfr = olFileRelate.GetHeadPosition();
for (DWORD n=0;n<=j;n++)
{
wfr = (CWavFileRelate*)olFileRelate.GetNext(pWfr);
}
DWORD dwFileInfoId = wfr->m_dwFileInfoId;
pWfi = olFileInfo.GetHeadPosition();
for (n=0;n<=dwFileInfoId;n++)
{
wfi = (CWavFileInfo*)olFileInfo.GetNext(pWfi);
}
CFile *fTrimFile;
fTrimFile = wfi->m_fFile;
if (((wci->m_dbStoryIn)*48000<=i)&&((wci->m_dbStoryIn+wci->m_dbTrimOut-wci->m_dbTrimIn)*48000>i))
{
fTrimFile->Seek((i+DWORD((wci->m_dbTrimIn-wci->m_dbStoryIn)*48000)-wfi->m_dwPosition)*4,CFile::current);
fTrimFile->Read(&sTrimLeft,2);
if (wci->m_bLeft == FALSE)
sTrimLeft = 0;
sTotalTrimLeft += sTrimLeft;
fTrimFile->Read(&sTrimRight,2);
if (wci->m_bRight == FALSE)
sTrimRight = 0;
sTotalTrimRight += sTrimRight;
wfi->m_dwPosition = i + DWORD((wci->m_dbTrimIn - wci->m_dbStoryIn)*48000) + 1;
}
}
sStoryLeft+=sTotalTrimLeft;
sStoryRight+=sTotalTrimRight;
fComposeFile.Seek(-4,CFile::current);
fComposeFile.Write(&sStoryLeft,2);
fComposeFile.Write(&sStoryRight,2);
}
pWfi = olFileInfo.GetHeadPosition();
dwCount = olFileInfo.GetCount();
for (i=0;i<dwCount;i++)
{
wfi = (CWavFileInfo*)olFileInfo.GetNext(pWfi);
wfi->m_fFile->Close();
}
ProgDlg.Close();
olFileInfo.DeleteAll();
olFileRelate.DeleteAll();
fComposeFile.Close();
return TRUE;
}
以上是我以前写的一段程序,你主要看wave合成就可以了,分割跟合成类似。