348 lines
8.8 KiB
C++
348 lines
8.8 KiB
C++
// File: waveio.cpp
|
|
|
|
#include "precomp.h"
|
|
#include "waveio.h"
|
|
|
|
|
|
|
|
//==========================================================================;
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (C) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// waveio.c
|
|
//
|
|
// Description:
|
|
// Contains routines for opening and closing RIFF WAVE files.
|
|
//
|
|
//
|
|
//==========================================================================;
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// WIOERR wioFileClose
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
// LPWAVEIOCB pwio:
|
|
//
|
|
// DWORD fdwClose:
|
|
//
|
|
// Return (WIOERR):
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
WIOERR WIOAPI wioFileClose
|
|
(
|
|
LPWAVEIOCB pwio,
|
|
DWORD fdwClose
|
|
)
|
|
{
|
|
//
|
|
// validate a couple of things...
|
|
//
|
|
if (NULL == pwio)
|
|
return (WIOERR_BADPARAM);
|
|
|
|
|
|
//
|
|
// get rid of stuff...
|
|
//
|
|
// wioStopWave(pwio);
|
|
|
|
if (NULL != pwio->hmmio)
|
|
{
|
|
mmioClose(pwio->hmmio, 0);
|
|
}
|
|
|
|
// FreeWaveHeaders(lpwio);
|
|
|
|
#if 0
|
|
if (pwio->pInfo)
|
|
riffFreeINFO(&(lpwio->pInfo));
|
|
|
|
if (pwio->pDisp)
|
|
riffFreeDISP(&(lpwio->pDisp));
|
|
#endif
|
|
|
|
if (NULL != pwio->pwfx)
|
|
GlobalFreePtr(pwio->pwfx);
|
|
|
|
_fmemset(pwio, 0, sizeof(*pwio));
|
|
|
|
return (WIOERR_NOERROR);
|
|
} // wioFileClose()
|
|
|
|
|
|
//--------------------------------------------------------------------------;
|
|
//
|
|
// WIOERR wioFileOpen
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
// LPWAVEIOCB pwio:
|
|
//
|
|
// LPCTSTR pszFilePath:
|
|
//
|
|
// DWORD fdwOpen:
|
|
//
|
|
// Return (WIOERR):
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
WIOERR WIOAPI wioFileOpen
|
|
(
|
|
LPWAVEIOCB pwio,
|
|
LPCTSTR pszFilePath,
|
|
DWORD fdwOpen
|
|
)
|
|
{
|
|
WIOERR werr;
|
|
HMMIO hmmio;
|
|
MMCKINFO ckRIFF;
|
|
MMCKINFO ck;
|
|
DWORD dw;
|
|
|
|
//
|
|
// validate a couple of things...
|
|
//
|
|
if (NULL == pwio)
|
|
return (WIOERR_BADPARAM);
|
|
|
|
//
|
|
// default our error return (assume the worst)
|
|
//
|
|
_fmemset(pwio, 0, sizeof(*pwio));
|
|
werr = WIOERR_FILEERROR;
|
|
|
|
pwio->dwFlags = fdwOpen;
|
|
|
|
//
|
|
// first try to open the file, etc.. open the given file for reading
|
|
// using buffered I/O
|
|
//
|
|
hmmio = mmioOpen((LPTSTR)pszFilePath, NULL, MMIO_READ | MMIO_ALLOCBUF);
|
|
if (NULL == hmmio)
|
|
goto wio_Open_Error;
|
|
|
|
pwio->hmmio = hmmio;
|
|
|
|
|
|
//
|
|
// locate a 'WAVE' form type...
|
|
//
|
|
ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
|
|
if (mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF))
|
|
goto wio_Open_Error;
|
|
|
|
//
|
|
// we found a WAVE chunk--now go through and get all subchunks that
|
|
// we know how to deal with...
|
|
//
|
|
pwio->dwDataSamples = (DWORD)-1L;
|
|
|
|
#if 0
|
|
if (lrt=riffInitINFO(&wio.pInfo))
|
|
{
|
|
lr=lrt;
|
|
goto wio_Open_Error;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//
|
|
//
|
|
while (MMSYSERR_NOERROR == mmioDescend(hmmio, &ck, &ckRIFF, 0))
|
|
{
|
|
//
|
|
// quickly check for corrupt RIFF file--don't ascend past end!
|
|
//
|
|
if ((ck.dwDataOffset + ck.cksize) > (ckRIFF.dwDataOffset + ckRIFF.cksize))
|
|
{
|
|
// TCHAR ach[255];
|
|
// wsprintf(ach, TEXT("This wave file might be corrupt. The RIFF chunk.ckid '%.08lX' (data offset at %lu) specifies a cksize of %lu that extends beyond what the RIFF header cksize of %lu allows. Attempt to load?"),
|
|
// ck.ckid, ck.dwDataOffset, ck.cksize, ckRIFF.cksize);
|
|
// u = MessageBox(NULL, ach, TEXT("wioFileOpen"),
|
|
// MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
|
|
// if (IDNO == u)
|
|
// {
|
|
werr = WIOERR_BADFILE;
|
|
goto wio_Open_Error;
|
|
// }
|
|
}
|
|
|
|
switch (ck.ckid)
|
|
{
|
|
case mmioFOURCC('L', 'I', 'S', 'T'):
|
|
if (ck.fccType == mmioFOURCC('I', 'N', 'F', 'O'))
|
|
{
|
|
#if 0
|
|
if(lrt=riffReadINFO(hmmio, &ck, wio.pInfo))
|
|
{
|
|
lr=lrt;
|
|
goto wio_Open_Error;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case mmioFOURCC('D', 'I', 'S', 'P'):
|
|
#if 0
|
|
riffReadDISP(hmmio, &ck, &(wio.pDisp));
|
|
#endif
|
|
break;
|
|
|
|
case mmioFOURCC('f', 'm', 't', ' '):
|
|
//
|
|
// !?! another format chunk !?!
|
|
//
|
|
if (NULL != pwio->pwfx)
|
|
break;
|
|
|
|
//
|
|
// get size of the format chunk, allocate and lock memory
|
|
// for it. we always alloc a complete extended format header
|
|
// (even for PCM headers that do not have the cbSize field
|
|
// defined--we just set it to zero).
|
|
//
|
|
dw = ck.cksize;
|
|
if (dw < sizeof(WAVEFORMATEX))
|
|
dw = sizeof(WAVEFORMATEX);
|
|
|
|
pwio->pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, dw);
|
|
if (NULL == pwio->pwfx)
|
|
{
|
|
werr = WIOERR_NOMEM;
|
|
goto wio_Open_Error;
|
|
}
|
|
|
|
//
|
|
// read the format chunk
|
|
//
|
|
werr = WIOERR_FILEERROR;
|
|
dw = ck.cksize;
|
|
if (mmioRead(hmmio, (HPSTR)pwio->pwfx, dw) != (LONG)dw)
|
|
goto wio_Open_Error;
|
|
break;
|
|
|
|
|
|
case mmioFOURCC('d', 'a', 't', 'a'):
|
|
//
|
|
// !?! multiple data chunks !?!
|
|
//
|
|
if (0L != pwio->dwDataBytes)
|
|
break;
|
|
|
|
//
|
|
// just hang on to the total length in bytes of this data
|
|
// chunk.. and the offset to the start of the data
|
|
//
|
|
pwio->dwDataBytes = ck.cksize;
|
|
pwio->dwDataOffset = ck.dwDataOffset;
|
|
break;
|
|
|
|
|
|
case mmioFOURCC('f', 'a', 'c', 't'):
|
|
//
|
|
// !?! multiple fact chunks !?!
|
|
//
|
|
if (-1L != pwio->dwDataSamples)
|
|
break;
|
|
|
|
//
|
|
// read the first dword in the fact chunk--it's the only
|
|
// info we need (and is currently the only info defined for
|
|
// the fact chunk...)
|
|
//
|
|
// if this fails, dwDataSamples will remain -1 so we will
|
|
// deal with it later...
|
|
//
|
|
mmioRead(hmmio, (HPSTR)&pwio->dwDataSamples, sizeof(DWORD));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// step up to prepare for next chunk..
|
|
//
|
|
mmioAscend(hmmio, &ck, 0);
|
|
}
|
|
|
|
//
|
|
// if no fmt chunk was found, then die!
|
|
//
|
|
if (NULL == pwio->pwfx)
|
|
{
|
|
werr = WIOERR_ERROR;
|
|
goto wio_Open_Error;
|
|
}
|
|
|
|
//
|
|
// all wave files other than PCM are _REQUIRED_ to have a fact chunk
|
|
// telling the number of samples that are contained in the file. it
|
|
// is optional for PCM (and if not present, we compute it here).
|
|
//
|
|
// if the file is not PCM and the fact chunk is not found, then fail!
|
|
//
|
|
if (-1L == pwio->dwDataSamples)
|
|
{
|
|
if (WAVE_FORMAT_PCM == pwio->pwfx->wFormatTag)
|
|
{
|
|
pwio->dwDataSamples = pwio->dwDataBytes / pwio->pwfx->nBlockAlign;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// !!! HACK HACK HACK !!!
|
|
//
|
|
// although this should be considered an invalid wave file, we
|
|
// will bring up a message box describing the error--hopefully
|
|
// people will start realizing that something is missing???
|
|
//
|
|
// u = MessageBox(NULL, TEXT("This wave file does not have a 'fact' chunk and requires one! This is completely invalid and MUST be fixed! Attempt to load it anyway?"),
|
|
// TEXT("wioFileOpen"), MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
|
|
// if (IDNO == u)
|
|
// {
|
|
werr = WIOERR_BADFILE;
|
|
goto wio_Open_Error;
|
|
// }
|
|
|
|
//
|
|
// !!! need to hack stuff in here !!!
|
|
//
|
|
pwio->dwDataSamples = 0L;
|
|
}
|
|
}
|
|
|
|
//
|
|
// cool! no problems..
|
|
//
|
|
return (WIOERR_NOERROR);
|
|
|
|
|
|
//
|
|
// return error (after minor cleanup)
|
|
//
|
|
wio_Open_Error:
|
|
|
|
wioFileClose(pwio, 0L);
|
|
return (werr);
|
|
} // wioFileOpen()
|
|
|
|
|
|
|
|
|