www.pudn.com > 组态软件的语音处理.rar > WAVE.CPP


// wave.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "wave.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char BASED_CODE THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CWave 
 
IMPLEMENT_SERIAL(CWave, CObject, 0 /* Schema number */ ) 
 
// Create a simple waveform so there's something there. 
CWave::CWave() 
{ 
    m_pSamples = NULL; 
    m_pOutDev = NULL; 
    m_bBusy = FALSE; 
    Create(16); 
} 
 
CWave::~CWave() 
{ 
    if (m_bBusy) { 
        Stop(); 
    } 
    ASSERT(!m_bBusy); // May be a problem here. 
    if (m_pSamples) free(m_pSamples); 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CWave serialization 
 
void CWave::Serialize(CArchive& ar) 
{ 
    ar.Flush(); 
    CFile* fp = ar.GetFile(); 
 
    if (ar.IsStoring()) { 
        ASSERT(1); // Save(fp); 
    } else { 
        Load(fp); 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////// 
// CWave notification functions 
 
void CWave::OnWaveOutDone() 
{ 
 
} 
 
void CWave::OnWaveInData() 
{ 
 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CWave commands 
 
BOOL CWave::Create(int nsamples, int samprate, int sampsize) 
{ 
    // Validate the arguments. 
    if ((samprate != 11025) 
    && (samprate != 22050) 
    && (samprate != 44100)) { 
        TRACE("Invalid sample rate: %d", samprate); 
        return FALSE; 
    } 
    if ((sampsize != 8) && (sampsize != 16)) { 
        TRACE("Invalid sample size: %d", sampsize); 
        return FALSE; 
    } 
 
    // Allocate memory for the samples. 
    int iBytes = nsamples * sampsize / 8; 
    void* pSamples = malloc(iBytes); 
    if (!pSamples) { 
        TRACE("Out of memory for samples"); 
        return FALSE; 
    } 
 
    // Free existing memory and replace it. 
    if (m_pSamples) free(m_pSamples); 
    m_pSamples = pSamples; 
    m_iSize = iBytes; 
     
    // Fill out the format information. 
    m_pcmfmt.wf.wFormatTag = WAVE_FORMAT_PCM; 
    m_pcmfmt.wf.nChannels = 1; // We only do mono. 
    m_pcmfmt.wf.nSamplesPerSec = samprate; 
    m_pcmfmt.wf.nAvgBytesPerSec = samprate; 
    m_pcmfmt.wf.nBlockAlign = sampsize / 8; // Number of bytes. 
    m_pcmfmt.wBitsPerSample = sampsize;  
 
    // Set the buffer to silence. 
    for (int i=0; iPlay(this); 
    } else { 
        m_pOutDev = &theDefaultWaveOutDevice; 
        return theDefaultWaveOutDevice.Play(this); 
    } 
} 
 
void CWave::Stop() 
{ 
    if (!m_bBusy) return; 
 
    ASSERT(m_pOutDev); 
    m_pOutDev->Stop(); 
} 
 
BOOL CWave::Load(char* pszFileName) 
{ 
    CString strFile;     
 
    if ((pszFileName == NULL)  
    ||  (strlen(pszFileName) == 0)) { 
 
        // Show an Open File dialog to get the name 
        CFileDialog dlg   (TRUE,    // Open 
                           NULL,    // No default extension 
                           NULL,    // No initial file name 
                           OFN_FILEMUSTEXIST 
                             | OFN_HIDEREADONLY, 
                           "Wave files (*.WAV)|*.WAV|All files (*.*)|*.*||"); 
        if (dlg.DoModal() == IDOK) { 
            strFile = dlg.GetPathName(); 
        } else { 
            return FALSE; 
        } 
    } else {     
        // Copy the supplied file path. 
        strFile = pszFileName;                     
    } 
 
    // Try to open the file for read access. 
    CFile file; 
    if (! file.Open(strFile, 
                    CFile::modeRead | CFile::shareDenyWrite)) { 
        AfxMessageBox("Failed to open file"); 
        return FALSE; 
    } 
 
    BOOL bResult = Load(&file); 
    file.Close(); 
    if (!bResult) AfxMessageBox("Failed to load file"); 
    return bResult; 
} 
 
BOOL CWave::Load(CFile* fp) 
{ 
    return Load(fp->m_hFile); 
} 
 
BOOL CWave::Load(UINT hFile) 
{ 
    HMMIO hmmio; 
    MMIOINFO info; 
    memset(&info, 0, sizeof(info)); 
    info.adwInfo[0] = hFile; 
    hmmio = mmioOpen(NULL, 
                     &info, 
                     MMIO_READ | MMIO_ALLOCBUF); 
    if (!hmmio) { 
        TRACE("mmioOpen failed"); 
        return FALSE; 
    } 
    BOOL bResult = Load(hmmio); 
    mmioClose(hmmio, MMIO_FHOPEN); 
    return bResult; 
} 
 
BOOL CWave::Load(HMMIO hmmio) 
{ 
    // Check whether it's a RIFF WAVE file. 
    MMCKINFO ckFile; 
    ckFile.fccType = mmioFOURCC('W','A','V','E'); 
    if (mmioDescend(hmmio, 
                    &ckFile, 
                    NULL, 
                    MMIO_FINDRIFF) != 0) { 
        TRACE("Not a RIFF or WAVE file"); 
        return FALSE; 
    } 
    // Find the 'fmt ' chunk. 
    MMCKINFO ckChunk; 
    ckChunk.ckid = mmioFOURCC('f','m','t',' '); 
    if (mmioDescend(hmmio, 
                    &ckChunk, 
                    &ckFile, 
                    MMIO_FINDCHUNK) != 0) { 
        TRACE("No fmt chunk in file"); 
        return FALSE; 
    } 
    // Allocate some memory for the fmt chunk. 
    int iSize = ckChunk.cksize; 
    WAVEFORMAT* pfmt = (WAVEFORMAT*) malloc(iSize); 
    ASSERT(pfmt); 
    // Read the fmt chunk. 
    if (mmioRead(hmmio, 
                 (char*)pfmt, 
                 iSize) != iSize) { 
        TRACE("Failed to read fmt chunk"); 
        free(pfmt); 
        return FALSE; 
    } 
    // Check whether it's in PCM format. 
    if (pfmt->wFormatTag != WAVE_FORMAT_PCM) { 
        TRACE("Not a PCM file"); 
        free(pfmt); 
        return FALSE; 
    } 
    // Get out of the fmt chunk. 
    mmioAscend(hmmio, &ckChunk, 0); 
    // Find the 'data' chunk. 
    ckChunk.ckid = mmioFOURCC('d','a','t','a'); 
    if (mmioDescend(hmmio, 
                    &ckChunk, 
                    &ckFile, 
                    MMIO_FINDCHUNK) != 0) { 
        TRACE("No data chunk in file"); 
        free(pfmt); 
        return FALSE; 
    } 
    // Allocate some memory for the data chunk. 
    iSize = ckChunk.cksize; 
    void* pdata = malloc(iSize); 
    if (!pdata) { 
        TRACE("No mem for data"); 
        free(pfmt); 
        return FALSE; 
    } 
    // Read the data chunk. 
    if (mmioRead(hmmio, 
                 (char*)pdata, 
                 iSize) != iSize) { 
        TRACE("Failed to read data chunk"); 
        free(pfmt); 
        free(pdata); 
        return FALSE; 
    } 
    // Wrap the CWave object around what we have. 
    memcpy(&m_pcmfmt, pfmt, sizeof(m_pcmfmt)); 
    // Replace the samples. 
    if (m_pSamples) free(m_pSamples); 
    m_pSamples = pdata; 
    m_iSize = iSize; 
 
    return TRUE; 
} 
 
// Get the number of samples. 
int CWave::GetNumSamples() 
{ 
    ASSERT(m_pcmfmt.wBitsPerSample); 
    return m_iSize * 8 / m_pcmfmt.wBitsPerSample; 
} 
 
// Get a sample value scaled as a 16 bit signed quantity. 
int CWave::GetSample(int index) 
{ 
    if ((index < 0) || (index >= GetNumSamples())) { 
        TRACE("Sample index out of range"); 
        return 0; 
    } 
    switch (m_pcmfmt.wBitsPerSample) { 
    case 8: { 
        BYTE* p = (BYTE*) m_pSamples; 
        int i = p[index]; // 0 through 255; 
        return (i - 128) * 256; 
        } break; 
 
    case 16: { 
        ASSERT(sizeof(short int) == 2); 
        short int* p = (short int*) m_pSamples; 
        return p[index]; 
        } break; 
         
    default: 
        break; 
    } 
    ASSERT(1); // Invalid bits per sample 
    return 0; 
}             
 
// Set a sample value from a 16 bit signed quantity. 
void CWave::SetSample(int index, int iValue) 
{ 
    if ((index < 0) || (index >= GetNumSamples())) { 
        TRACE("Sample index out of range"); 
        return; 
    } 
    switch (m_pcmfmt.wBitsPerSample) { 
    case 8: { 
        BYTE* p = (BYTE*) m_pSamples; 
        p[index] = iValue / 256 + 128; 
        } break; 
 
    case 16: { 
        ASSERT(sizeof(short int) == 16); 
        short int* p = (short int*) m_pSamples; 
        p[index] = iValue; 
        } break; 
         
    default: 
        ASSERT(1); // Invalid bits per sample 
        break; 
    } 
}