genesis-3d_engine/Engine/addons/soundsystem/CWaves.cc

866 lines
22 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2006, Creative Labs Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "stdneb.h"
#include "CWaves.h"
#include <errno.h>
#include "io/stream.h"
#ifdef __WIN32__
#include <ks.h>
#include <mmsystem.h>
#include <ksmedia.h>
#else
typedef long HRESULT;
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define _MAX_PATH 260
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _strdup strdup
#define WAVE_FORMAT_PCM 1
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#define SPEAKER_FRONT_LEFT 0x1
#define SPEAKER_FRONT_RIGHT 0x2
#define SPEAKER_FRONT_CENTER 0x4
#define SPEAKER_LOW_FREQUENCY 0x8
#define SPEAKER_BACK_LEFT 0x10
#define SPEAKER_BACK_RIGHT 0x20
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
#define SPEAKER_BACK_CENTER 0x100
#define SPEAKER_SIDE_LEFT 0x200
#define SPEAKER_SIDE_RIGHT 0x400
#define SPEAKER_TOP_CENTER 0x800
#define SPEAKER_TOP_FRONT_LEFT 0x1000
#define SPEAKER_TOP_FRONT_CENTER 0x2000
#define SPEAKER_TOP_FRONT_RIGHT 0x4000
#define SPEAKER_TOP_BACK_LEFT 0x8000
#define SPEAKER_TOP_BACK_CENTER 0x10000
#define SPEAKER_TOP_BACK_RIGHT 0x20000
typedef struct waveformat_tag {
WORD wFormatTag; /* format type */
WORD nChannels; /* number of channels (i.e. mono, stereo, etc.) */
DWORD nSamplesPerSec; /* sample rate */
DWORD nAvgBytesPerSec; /* for buffer estimation */
WORD nBlockAlign; /* block size of data */
} WAVEFORMAT;
typedef struct pcmwaveformat_tag {
WAVEFORMAT wf;
WORD wBitsPerSample;
} PCMWAVEFORMAT;
#endif //__ANDROID__
#pragma pack(push, 4)
typedef struct
{
char szRIFF[4];
unsigned long ulRIFFSize;
char szWAVE[4];
} WAVEFILEHEADER;
typedef struct
{
char szChunkName[4];
unsigned long ulChunkSize;
} RIFFCHUNK;
typedef struct
{
unsigned short usFormatTag;
unsigned short usChannels;
unsigned long ulSamplesPerSec;
unsigned long ulAvgBytesPerSec;
unsigned short usBlockAlign;
unsigned short usBitsPerSample;
unsigned short usSize;
unsigned short usReserved;
unsigned long ulChannelMask;
GUID guidSubFormat;
} WAVEFMT;
#pragma pack(pop)
#if _MSC_VER <= 1310
// Wrap around the deprecated functions for VS2003 support
int fopen_s( FILE** pFile, const char *filename, const char *mode )
{
*pFile = fopen( filename, mode );
return *pFile ? 0 : EBADF;
}
int strncpy_s( char *strDest, size_t numberOfElements, const char *strSource, size_t count )
{
strncpy( strDest, strSource, count );
return 0;
}
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CWaves::CWaves()
{
memset(&m_WaveIDs, 0, sizeof(m_WaveIDs));
}
CWaves::~CWaves()
{
long lLoop;
for (lLoop = 0; lLoop < MAX_NUM_WAVEID; lLoop++)
{
if (m_WaveIDs[lLoop])
{
if (m_WaveIDs[lLoop]->pData)
delete m_WaveIDs[lLoop]->pData;
if (m_WaveIDs[lLoop]->pFile)
fclose(m_WaveIDs[lLoop]->pFile);
delete m_WaveIDs[lLoop];
m_WaveIDs[lLoop] = 0;
}
}
}
WAVERESULT CWaves::LoadWaveFile(const char* nameOrData, SizeT dataSize, WAVEID *pWaveID, bool bOpenMemory)
{
WAVERESULT wr = WR_OUTOFMEMORY;
LPWAVEFILEINFO pWaveInfo;
pWaveInfo = new WAVEFILEINFO;
if (pWaveInfo)
{
if ( bOpenMemory )
{
GPtr<IO::MemoryStream> pData = IO::MemoryStream::Create();
pData->SetAccessMode( IO::Stream::ReadWriteAccess );
pData->Open();
pData->Write(nameOrData, dataSize);
pData->Seek(0,IO::Stream::Begin);
if (SUCCEEDED(wr = ParseFile(pData, pWaveInfo)))
{
// Allocate memory for sample data
pWaveInfo->pData = new char[pWaveInfo->ulDataSize];
if (pWaveInfo->pData)
{
// Seek to start of audio data
pData->Seek(pWaveInfo->ulDataOffset, IO::Stream::Begin);
// Read Sample Data
if (pData->Read(pWaveInfo->pData, pWaveInfo->ulDataSize) == pWaveInfo->ulDataSize)
{
long lLoop = 0;
for (lLoop = 0; lLoop < MAX_NUM_WAVEID; lLoop++)
{
if (!m_WaveIDs[lLoop])
{
m_WaveIDs[lLoop] = pWaveInfo;
*pWaveID = lLoop;
wr = WR_OK;
break;
}
}
if (lLoop == MAX_NUM_WAVEID)
{
delete pWaveInfo->pData;
wr = WR_OUTOFMEMORY;
}
}
else
{
delete pWaveInfo->pData;
wr = WR_BADWAVEFILE;
}
}
else
{
wr = WR_OUTOFMEMORY;
}
pData->Close();
}
}
else
{
if (SUCCEEDED(wr = ParseFile(nameOrData, pWaveInfo)))
{
// Allocate memory for sample data
pWaveInfo->pData = new char[pWaveInfo->ulDataSize];
if (pWaveInfo->pData)
{
// Seek to start of audio data
fseek(pWaveInfo->pFile, pWaveInfo->ulDataOffset, SEEK_SET);
// Read Sample Data
if (fread(pWaveInfo->pData, 1, pWaveInfo->ulDataSize, pWaveInfo->pFile) == pWaveInfo->ulDataSize)
{
long lLoop = 0;
for (lLoop = 0; lLoop < MAX_NUM_WAVEID; lLoop++)
{
if (!m_WaveIDs[lLoop])
{
m_WaveIDs[lLoop] = pWaveInfo;
*pWaveID = lLoop;
wr = WR_OK;
break;
}
}
if (lLoop == MAX_NUM_WAVEID)
{
delete pWaveInfo->pData;
wr = WR_OUTOFMEMORY;
}
}
else
{
delete pWaveInfo->pData;
wr = WR_BADWAVEFILE;
}
}
else
{
wr = WR_OUTOFMEMORY;
}
fclose(pWaveInfo->pFile);
pWaveInfo->pFile = 0;
}
}
if (wr != WR_OK)
delete pWaveInfo;
}
return wr;
}
#ifdef zhaohang
WAVERESULT CWaves::OpenWaveFile(const char* nameOrData, SizeT dataSize, WAVEID *pWaveID, bool bOpenMemory)
{
WAVERESULT wr = WR_OUTOFMEMORY;
LPWAVEFILEINFO pWaveInfo;
pWaveInfo = new WAVEFILEINFO;
if (pWaveInfo)
{
if ( !bOpenMemory )
{
if (SUCCEEDED(wr = ParseFile(nameOrData, pWaveInfo)))
{
long lLoop = 0;
for (lLoop = 0; lLoop < MAX_NUM_WAVEID; lLoop++)
{
if (!m_WaveIDs[lLoop])
{
m_WaveIDs[lLoop] = pWaveInfo;
*pWaveID = lLoop;
wr = WR_OK;
break;
}
}
if (lLoop == MAX_NUM_WAVEID)
wr = WR_OUTOFMEMORY;
}
}
if (wr != WR_OK)
delete pWaveInfo;
}
return wr;
}
WAVERESULT CWaves::ReadWaveData(WAVEID WaveID, void *pData, unsigned long ulDataSize, unsigned long *pulBytesWritten)
{
LPWAVEFILEINFO pWaveInfo;
WAVERESULT wr = WR_BADWAVEFILE;
if (!pData || !pulBytesWritten || ulDataSize == 0)
return WR_INVALIDPARAM;
if (IsWaveID(WaveID))
{
pWaveInfo = m_WaveIDs[WaveID];
if (pWaveInfo->pFile)
{
unsigned long ulOffset = ftell(pWaveInfo->pFile);
if ((ulOffset - pWaveInfo->ulDataOffset + ulDataSize) > pWaveInfo->ulDataSize)
ulDataSize = pWaveInfo->ulDataSize - (ulOffset - pWaveInfo->ulDataOffset);
*pulBytesWritten = (unsigned long)fread(pData, 1, ulDataSize, pWaveInfo->pFile);
wr = WR_OK;
}
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}
WAVERESULT CWaves::SetWaveDataOffset(WAVEID WaveID, unsigned long ulOffset)
{
LPWAVEFILEINFO pWaveInfo;
WAVERESULT wr = WR_INVALIDPARAM;
if (IsWaveID(WaveID))
{
pWaveInfo = m_WaveIDs[WaveID];
if (pWaveInfo->pFile)
{
// Seek into audio data
fseek(pWaveInfo->pFile, pWaveInfo->ulDataOffset + ulOffset, SEEK_SET);
wr = WR_OK;
}
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}
WAVERESULT CWaves::GetWaveDataOffset(WAVEID WaveID, unsigned long *pulOffset)
{
LPWAVEFILEINFO pWaveInfo;
WAVERESULT wr = WR_INVALIDPARAM;
if (IsWaveID(WaveID))
{
pWaveInfo = m_WaveIDs[WaveID];
if ((pWaveInfo->pFile) && (pulOffset))
{
// Get current position
*pulOffset = ftell(pWaveInfo->pFile);
*pulOffset -= pWaveInfo->ulDataOffset;
wr = WR_OK;
}
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}
#endif
WAVERESULT CWaves::ParseFile(const char *szFilename, LPWAVEFILEINFO pWaveInfo)
{
WAVEFILEHEADER waveFileHeader;
RIFFCHUNK riffChunk;
WAVEFMT waveFmt;
WAVERESULT wr = WR_BADWAVEFILE;
if (!szFilename || !pWaveInfo)
return WR_INVALIDPARAM;
memset(pWaveInfo, 0, sizeof(WAVEFILEINFO));
// Open the wave file for reading
fopen_s(&pWaveInfo->pFile, szFilename, "rb");
if (pWaveInfo->pFile)
{
// Read Wave file header
fread(&waveFileHeader, 1, sizeof(WAVEFILEHEADER), pWaveInfo->pFile);
if (!_strnicmp(waveFileHeader.szRIFF, "RIFF", 4) && !_strnicmp(waveFileHeader.szWAVE, "WAVE", 4))
{
while (fread(&riffChunk, 1, sizeof(RIFFCHUNK), pWaveInfo->pFile) == sizeof(RIFFCHUNK))
{
if (!_strnicmp(riffChunk.szChunkName, "fmt ", 4))
{
if (riffChunk.ulChunkSize <= sizeof(WAVEFMT))
{
fread(&waveFmt, 1, riffChunk.ulChunkSize, pWaveInfo->pFile);
// Determine if this is a WAVEFORMATEX or WAVEFORMATEXTENSIBLE wave file
if (waveFmt.usFormatTag == WAVE_FORMAT_PCM)
{
pWaveInfo->wfType = WF_EX;
memcpy(&pWaveInfo->wfEXT.Format, &waveFmt, sizeof(PCMWAVEFORMAT));
}
else if (waveFmt.usFormatTag == WAVE_FORMAT_EXTENSIBLE)
{
pWaveInfo->wfType = WF_EXT;
memcpy(&pWaveInfo->wfEXT, &waveFmt, sizeof(WAVEFORMATEXTENSIBLE));
}
}
else
{
fseek(pWaveInfo->pFile, riffChunk.ulChunkSize, SEEK_CUR);
}
}
else if (!_strnicmp(riffChunk.szChunkName, "data", 4))
{
pWaveInfo->ulDataSize = riffChunk.ulChunkSize;
pWaveInfo->ulDataOffset = ftell(pWaveInfo->pFile);
fseek(pWaveInfo->pFile, riffChunk.ulChunkSize, SEEK_CUR);
}
else
{
fseek(pWaveInfo->pFile, riffChunk.ulChunkSize, SEEK_CUR);
}
// Ensure that we are correctly aligned for next chunk
if (riffChunk.ulChunkSize & 1)
fseek(pWaveInfo->pFile, 1, SEEK_CUR);
}
if (pWaveInfo->ulDataSize && pWaveInfo->ulDataOffset && ((pWaveInfo->wfType == WF_EX) || (pWaveInfo->wfType == WF_EXT)))
wr = WR_OK;
else
fclose(pWaveInfo->pFile);
}
}
else
{
wr = WR_INVALIDFILENAME;
}
return wr;
}
WAVERESULT CWaves::ParseFile(GPtr<IO::MemoryStream>& data, LPWAVEFILEINFO pWaveInfo)
{
WAVEFILEHEADER waveFileHeader;
RIFFCHUNK riffChunk;
WAVEFMT waveFmt;
WAVERESULT wr = WR_BADWAVEFILE;
if (!data.isvalid() || !pWaveInfo)
return WR_INVALIDPARAM;
memset(pWaveInfo, 0, sizeof(WAVEFILEINFO));
// Read Wave file header
data->Read(&waveFileHeader, sizeof(WAVEFILEHEADER));
if (!_strnicmp(waveFileHeader.szRIFF, "RIFF", 4) && !_strnicmp(waveFileHeader.szWAVE, "WAVE", 4))
{
while (data->Read(&riffChunk, sizeof(RIFFCHUNK)) == sizeof(RIFFCHUNK))
{
if (!_strnicmp(riffChunk.szChunkName, "fmt ", 4))
{
if (riffChunk.ulChunkSize <= sizeof(WAVEFMT))
{
data->Read(&waveFmt, riffChunk.ulChunkSize);
// Determine if this is a WAVEFORMATEX or WAVEFORMATEXTENSIBLE wave file
if (waveFmt.usFormatTag == WAVE_FORMAT_PCM)
{
pWaveInfo->wfType = WF_EX;
memcpy(&pWaveInfo->wfEXT.Format, &waveFmt, sizeof(PCMWAVEFORMAT));
}
else if (waveFmt.usFormatTag == WAVE_FORMAT_EXTENSIBLE)
{
pWaveInfo->wfType = WF_EXT;
memcpy(&pWaveInfo->wfEXT, &waveFmt, sizeof(WAVEFORMATEXTENSIBLE));
}
}
else
{
data->Seek(riffChunk.ulChunkSize, IO::Stream::Current);
}
}
else if (!_strnicmp(riffChunk.szChunkName, "data", 4))
{
pWaveInfo->ulDataSize = riffChunk.ulChunkSize;
pWaveInfo->ulDataOffset = data->GetPosition();
data->Seek(riffChunk.ulChunkSize, IO::Stream::Current);
}
else
{
data->Seek(riffChunk.ulChunkSize, IO::Stream::Current);
}
// Ensure that we are correctly aligned for next chunk
if (riffChunk.ulChunkSize & 1)
{
data->Seek(1, IO::Stream::Current);
}
}
if (pWaveInfo->ulDataSize && pWaveInfo->ulDataOffset && ((pWaveInfo->wfType == WF_EX) || (pWaveInfo->wfType == WF_EXT)))
wr = WR_OK;
else
data->Close();
}
return wr;
}
#ifdef zhaohang
WAVERESULT CWaves::GetWaveType(WAVEID WaveID, WAVEFILETYPE *wfType)
{
if (!IsWaveID(WaveID))
return WR_INVALIDWAVEID;
if (!wfType)
return WR_INVALIDPARAM;
*wfType = m_WaveIDs[WaveID]->wfType;
return WR_OK;
}
WAVERESULT CWaves::GetWaveFormatExHeader(WAVEID WaveID, WAVEFORMATEX *wfex)
{
if (!IsWaveID(WaveID))
return WR_INVALIDWAVEID;
if (!wfex)
return WR_INVALIDPARAM;
memcpy(wfex, &(m_WaveIDs[WaveID]->wfEXT.Format), sizeof(WAVEFORMATEX));
return WR_OK;
}
WAVERESULT CWaves::GetWaveFormatExtensibleHeader(WAVEID WaveID, WAVEFORMATEXTENSIBLE *wfext)
{
if (!IsWaveID(WaveID))
return WR_INVALIDWAVEID;
if (m_WaveIDs[WaveID]->wfType != WF_EXT)
return WR_NOTWAVEFORMATEXTENSIBLEFORMAT;
if (!wfext)
return WR_INVALIDPARAM;
memcpy(wfext, &(m_WaveIDs[WaveID]->wfEXT), sizeof(WAVEFORMATEXTENSIBLE));
return WR_OK;
}
char *CWaves::GetErrorString(WAVERESULT wr, char *szErrorString, unsigned long nSizeOfErrorString)
{
switch (wr)
{
case WR_OK:
strncpy_s(szErrorString, nSizeOfErrorString, "Success\n", nSizeOfErrorString-1);
break;
case WR_INVALIDFILENAME:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid file name or file does not exist\n", nSizeOfErrorString-1);
break;
case WR_BADWAVEFILE:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid Wave file\n", nSizeOfErrorString-1);
break;
case WR_INVALIDPARAM:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid parameter passed to function\n", nSizeOfErrorString-1);
break;
case WR_FILEERROR:
strncpy_s(szErrorString, nSizeOfErrorString, "File I/O error\n", nSizeOfErrorString-1);
break;
case WR_INVALIDWAVEID:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid WAVEID\n", nSizeOfErrorString-1);
break;
case WR_NOTSUPPORTEDYET:
strncpy_s(szErrorString, nSizeOfErrorString, "Function not supported yet\n", nSizeOfErrorString-1);
break;
case WR_WAVEMUSTBEMONO:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must be mono\n", nSizeOfErrorString-1);
break;
case WR_WAVEMUSTBEWAVEFORMATPCM:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must be in Wave Format PCM\n", nSizeOfErrorString-1);
break;
case WR_WAVESMUSTHAVESAMEBITRESOLUTION:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must have the same Bit Resolution\n", nSizeOfErrorString-1);
break;
case WR_WAVESMUSTHAVESAMEFREQUENCY:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must have the same Frequency\n", nSizeOfErrorString-1);
break;
case WR_WAVESMUSTHAVESAMEBITRATE:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must have the same Bit Rate\n", nSizeOfErrorString-1);
break;
case WR_WAVESMUSTHAVESAMEBLOCKALIGNMENT:
strncpy_s(szErrorString, nSizeOfErrorString, "Input wave files must have the same Block Alignment\n", nSizeOfErrorString-1);
break;
case WR_OFFSETOUTOFDATARANGE:
strncpy_s(szErrorString, nSizeOfErrorString, "Wave files Offset is not within audio data\n", nSizeOfErrorString-1);
break;
case WR_INVALIDSPEAKERPOS:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid Speaker Destinations\n", nSizeOfErrorString-1);
break;
case WR_OUTOFMEMORY:
strncpy_s(szErrorString, nSizeOfErrorString, "Out of memory\n", nSizeOfErrorString-1);
break;
case WR_INVALIDWAVEFILETYPE:
strncpy_s(szErrorString, nSizeOfErrorString, "Invalid Wave File Type\n", nSizeOfErrorString-1);
break;
case WR_NOTWAVEFORMATEXTENSIBLEFORMAT:
strncpy_s(szErrorString, nSizeOfErrorString, "Wave file is not in WAVEFORMATEXTENSIBLE format\n", nSizeOfErrorString-1);
break;
default:
strncpy_s(szErrorString, nSizeOfErrorString, "Undefined error\n", nSizeOfErrorString-1);
}
szErrorString[nSizeOfErrorString-1] = '\0';
return szErrorString;
}
#endif
WAVERESULT CWaves::GetWaveData(WAVEID WaveID, void **lplpAudioData)
{
if (!IsWaveID(WaveID))
return WR_INVALIDWAVEID;
if (!lplpAudioData)
return WR_INVALIDPARAM;
*lplpAudioData = m_WaveIDs[WaveID]->pData;
return WR_OK;
}
WAVERESULT CWaves::GetWaveSize(WAVEID WaveID, unsigned long *size)
{
if (!IsWaveID(WaveID))
return WR_INVALIDWAVEID;
if (!size)
return WR_INVALIDPARAM;
*size = m_WaveIDs[WaveID]->ulDataSize;
return WR_OK;
}
WAVERESULT CWaves::GetWaveFrequency(WAVEID WaveID, unsigned long *pulFrequency)
{
WAVERESULT wr = WR_OK;
if (IsWaveID(WaveID))
{
if (pulFrequency)
*pulFrequency = m_WaveIDs[WaveID]->wfEXT.Format.nSamplesPerSec;
else
wr = WR_INVALIDPARAM;
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}
bool CWaves::IsWaveID(WAVEID WaveID)
{
bool bReturn = false;
if ((WaveID >= 0) && (WaveID < MAX_NUM_WAVEID))
{
if (m_WaveIDs[WaveID])
bReturn = true;
}
return bReturn;
}
WAVERESULT CWaves::GetWaveALBufferFormat(WAVEID WaveID, PFNALGETENUMVALUE pfnGetEnumValue, unsigned long *pulFormat)
{
WAVERESULT wr = WR_OK;
if (IsWaveID(WaveID))
{
if (pfnGetEnumValue && pulFormat)
{
*pulFormat = 0;
if (m_WaveIDs[WaveID]->wfType == WF_EX)
{
if (m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 1)
{
switch (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample)
{
case 4:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO_IMA4");
break;
case 8:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO8");
break;
case 16:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO16");
break;
}
}
else if (m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 2)
{
switch (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample)
{
case 4:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO_IMA4");
break;
case 8:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO8");
break;
case 16:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO16");
break;
}
}
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 4) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16))
*pulFormat = pfnGetEnumValue("AL_FORMAT_QUAD16");
}
else if (m_WaveIDs[WaveID]->wfType == WF_EXT)
{
if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 1) &&
((m_WaveIDs[WaveID]->wfEXT.dwChannelMask == SPEAKER_FRONT_CENTER) ||
(m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)) ||
(m_WaveIDs[WaveID]->wfEXT.dwChannelMask == 0)))
{
switch (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample)
{
case 4:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO_IMA4");
break;
case 8:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO8");
break;
case 16:
*pulFormat = pfnGetEnumValue("AL_FORMAT_MONO16");
break;
}
}
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 2) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)))
{
switch (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample)
{
case 4:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO_IMA4");
break;
case 8:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO8");
break;
case 16:
*pulFormat = pfnGetEnumValue("AL_FORMAT_STEREO16");
break;
}
}
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 2) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)))
*pulFormat = pfnGetEnumValue("AL_FORMAT_REAR16");
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 4) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)))
*pulFormat = pfnGetEnumValue("AL_FORMAT_QUAD16");
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 6) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)))
*pulFormat = pfnGetEnumValue("AL_FORMAT_51CHN16");
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 7) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_BACK_CENTER)))
*pulFormat = pfnGetEnumValue("AL_FORMAT_61CHN16");
else if ((m_WaveIDs[WaveID]->wfEXT.Format.nChannels == 8) && (m_WaveIDs[WaveID]->wfEXT.Format.wBitsPerSample == 16) && (m_WaveIDs[WaveID]->wfEXT.dwChannelMask == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)))
*pulFormat = pfnGetEnumValue("AL_FORMAT_71CHN16");
}
if (*pulFormat == 0)
wr = WR_INVALIDWAVEFILETYPE;
}
else
{
wr = WR_INVALIDPARAM;
}
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}
WAVERESULT CWaves::DeleteWaveFile(WAVEID WaveID)
{
WAVERESULT wr = WR_OK;
if (IsWaveID(WaveID))
{
if (m_WaveIDs[WaveID]->pData)
delete[] m_WaveIDs[WaveID]->pData;
if (m_WaveIDs[WaveID]->pFile)
fclose(m_WaveIDs[WaveID]->pFile);
delete m_WaveIDs[WaveID];
m_WaveIDs[WaveID] = 0;
}
else
{
wr = WR_INVALIDWAVEID;
}
return wr;
}