WAVEIO.C

//==========================================================================; 
//
// 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 1992 - 1998 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// waveio.c
//
// Description:
// Contains routines for opening and closing RIFF WAVE files.
//
//
//==========================================================================;

#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <memory.h>

#include "appport.h"
#include "waveio.h"

#include "debug.h"


//--------------------------------------------------------------------------;
//
// 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
)
{
UINT u;
TCHAR ach[255];
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))
{
DPF(1, "wioFileOpen() FILE MIGHT BE CORRUPT!");
DPF(1, " ckRIFF.dwDataOffset: %lu", ckRIFF.dwDataOffset);
DPF(1, " ckRIFF.cksize: %lu", ckRIFF.cksize);
DPF(1, " ck.dwDataOffset: %lu", ck.dwDataOffset);
DPF(1, " ck.cksize: %lu", ck.cksize);

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()