www.pudn.com > PCMtoWave.rar > WaveDoc.cpp
// WaveDoc.cpp : implementation of the CWaveDoc class // #include "stdafx.h" #include "Wave.h" #include "WaveDoc.h" #include#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CWaveDoc IMPLEMENT_DYNCREATE(CWaveDoc, CDocument) BEGIN_MESSAGE_MAP(CWaveDoc, CDocument) //{{AFX_MSG_MAP(CWaveDoc) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWaveDoc construction/destruction CWaveDoc::CWaveDoc() { // TODO: add one-time construction code here fileOpened = FALSE; } CWaveDoc::~CWaveDoc() { if (fileOpened) { if (channels == 1) delete[] dm; else {delete[] dl; delete[] dr;} fileOpened = FALSE; } } BOOL CWaveDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CWaveDoc serialization #define ID_RIFF mmioFOURCC('R', 'I', 'F', 'F') #define ID_WAVE mmioFOURCC('W', 'A', 'V', 'E') #define ID_fmt mmioFOURCC('f', 'm', 't', ' ') #define ID_data mmioFOURCC('d', 'a', 't', 'a') void CWaveDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here if (fileOpened) { if (channels == 1) delete[] dm; else {delete[] dl; delete[] dr;} fileOpened = FALSE; } // // m_path=ar.GetFile()->GetFilePath(); play(); // BOOL format = FALSE, data = FALSE; WORD bytes; DWORD i, pos=12, fileSize = ar.GetFile()->GetLength(); float df; // unitary quantization step FOURCC id; DWORD fileLen, chkLen, sampleRate, avgBytesRate; WORD formatTag, bitsPerSample, extSize, blockAlign; // read RIFF header ar >> id; if (id != ID_RIFF) { MessageBox(NULL, "Not RIFF format!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } ar >> fileLen; if (fileLen != fileSize - 8) { MessageBox(NULL, "Wrong file size!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } // read wave id ar >> id; if (id != ID_WAVE) { MessageBox(NULL, "Not WAVE format!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } // read chunks while (!format || !data || pos < fileSize) { ar >> id; ar >> chkLen; if (id == ID_fmt) { // read format chunk ar >> formatTag; if (formatTag != 1) { MessageBox(NULL, "Not PCM format!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } ar >> channels; ar >> sampleRate; ar >> avgBytesRate; ar >> blockAlign; ar >> bitsPerSample; if (chkLen == 18) { ar >> extSize; char *buf = new char[extSize]; if (extSize > 0) ar.Read(buf, (UINT)extSize); delete[] buf; } else extSize = 0; pos += 8 + chkLen + extSize; format = TRUE; } else if (id == ID_data) { // read data chunk if (!format) { MessageBox(NULL, "No format chunk before data chunk!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } // validate and calculate parameters if (bitsPerSample <= 0) { MessageBox(NULL, "Wrong bits per sample!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } bytes = (WORD)((bitsPerSample + 7) / 8); if (bytes > 2) { MessageBox(NULL, "Too large bits per sample!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } n = chkLen / (channels * bytes); if (n <= 0) { MessageBox(NULL, "Sample number <= 0!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } //timeLen = (float)n / sampleRate; // calculate unitary quantization step df = 1.0f / (1l << (bitsPerSample - 1)); // read in sample data if (channels == 2) { // stereo // allocate memory for float sample data dl = new float[n]; dr = new float[n]; // allocate temporary memory and read sample data BYTE (*b2)[2]; short (*s2)[2]; if (bytes == 1) {b2 = new BYTE[n][2]; ar.Read(b2, n*2);} else {s2 = new short[n][2]; ar.Read(s2, n*4);} // convert sample to unitary float data for (i = 0; i < n; i ++ ) { dl[i] = ((bytes == 1) ? b2[i][0] - 128 : s2[i][0]) * df; dr[i] = ((bytes == 1) ? b2[i][1] - 128 : s2[i][1]) * df; } if (bytes == 1) delete[] b2; else delete[] s2; } else { // mono // allocate memory for float sample data dm = new float[n]; // allocate temporary memory and read sample data BYTE *b1; short *s1; if (bytes == 1) {b1 = new BYTE[n]; ar.Read(b1, n);} else {s1 = new short[n]; ar.Read(s1, n*2);} // convert sample to unitary float data for (i = 0; i < n; i ++ ) dm[i] = ((bytes == 1) ? b1[i] - 128 : s1[i]) * df; if (bytes == 1) delete[] b1; else delete[] s1; } pos += 8 + chkLen; data = TRUE; break; } else { //read other chunk char* buf = new char[chkLen]; ar.Read(buf, chkLen); pos += 8 + chkLen; delete[] buf; } } //ar.Close(); if (!format || !data) { MessageBox(NULL, "Wrong file data!", "Error", MB_OK); throw(new CFileException(CFileException::generic)); } fileOpened = TRUE; } } ///////////////////////////////////////////////////////////////////////////// // CWaveDoc diagnostics #ifdef _DEBUG void CWaveDoc::AssertValid() const { CDocument::AssertValid(); } void CWaveDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CWaveDoc commands void CWaveDoc::play() { PlaySound(m_path,NULL,SND_ASYNC); } void CWaveDoc::stop() { PlaySound(NULL,NULL,SND_ASYNC); }