Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

683 lines
15 KiB

//--------------------------------------------------------------------------;
//
// File: WaveUtil.c
//
// Copyright (C) Microsoft Corporation, 1993 - 1996 All rights reserved
//
// Abstract:
// Contains general utilities mostly to do with wave.
//
// Contents:
// wfxCpy()
// wfxCmp()
// GetFormatName()
// FormatFlag_To_Format()
//
// History:
// 11/24/93 Fwong Re-doing WaveTest.
//
//--------------------------------------------------------------------------;
#include <windows.h>
#ifdef WIN32
#include <windowsx.h>
#endif
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
#include <memory.h>
#include "waveutil.h"
#ifdef WIN32
#ifndef _HUGE
#define _HUGE
#endif
#ifndef lstrcpyn
#define lstrcpyn strncpy
#endif
#else
#ifndef _HUGE
#define _HUGE huge
#endif
#endif
//==========================================================================;
//
// Structures...
//
//==========================================================================;
typedef struct enumtype_tag
{
DWORD dwCount;
DWORD dwTarget;
} ENUMTYPE;
typedef ENUMTYPE *PENUMTYPE;
typedef ENUMTYPE NEAR *NPENUMTYPE;
typedef ENUMTYPE FAR *LPENUMTYPE;
//--------------------------------------------------------------------------;
//
// BOOL BufferCompare
//
// Description:
// Compares the contents of two buffers.
//
// Note: This *needs* to work across segments _fmemcmp may not always
// work.
//
// Arguments:
// LPBYTE pSrc: Pointer to first buffer.
//
// LPBYTE pDst: Pointer to second buffer.
//
// DWORD dwSize: Number of bytes to compare.
//
// Return (BOOL):
// returns TRUE if contents are similar, FALSE otherwise.
//
// History:
// 08/23/93 Fwong To verify structure similarity.
//
//--------------------------------------------------------------------------;
BOOL mem_cmp
(
LPBYTE pSrc,
LPBYTE pDst,
DWORD dwSize
)
{
BYTE _HUGE *pSource;
BYTE _HUGE *pDestination;
pSource = pSrc;
pDestination = pDst;
for(;dwSize;dwSize--)
{
if(pSource[(dwSize-1)] != pDestination[(dwSize-1)])
{
return FALSE;
}
}
return TRUE;
} // mem_cmp()
//--------------------------------------------------------------------------;
//
// void wfxCpy
//
// Description:
// Copies one wave format to another... Independent of size.
// Uses cbSize (if not PCM) to determine number of remaining bytes.
//
// Arguments:
// LPWAVEFORMATEX lpwfxDst: Destination wave format.
//
// LPWAVEFORMATEX lpwfxSrc: Source wave format.
//
// Return (void):
//
// History:
// 03/27/93 Fwong Created to facilitate things...
//
//--------------------------------------------------------------------------;
void FNGLOBAL wfxCpy
(
LPWAVEFORMATEX pwfxDst,
LPWAVEFORMATEX pwfxSrc
)
{
DWORD dwBufferSize;
//
// Warning!!! Assumes no cross segment copying...
//
dwBufferSize = SIZEOFWAVEFORMAT(pwfxSrc);
if(IsBadWritePtr(pwfxDst,(UINT)dwBufferSize))
{
return;
}
//
// Warning!!! Will not work with formats > 64K for Win16
//
_fmemcpy(pwfxDst,pwfxSrc,(UINT)dwBufferSize);
} // wfxCpy()
//--------------------------------------------------------------------------;
//
// BOOL wfxCmp
//
// Description:
// Compares the contents of the two WAVEFORMATEX structures.
// Note: Does intelligent compare including contents after cbSize.
//
// Arguments:
// LPWAVEFORMATEX pwfxSrc: Pointer to first WAVEFORMATEX structure.
//
// LPWAVEFORMATEX pwfxDst: Pointer to second WAVEFORMATEX structure.
//
// Return (BOOL):
// TRUE if formats are similar, FALSE otherwise.
//
// History:
// 08/25/93 Fwong To verify structure similarity.
//
//--------------------------------------------------------------------------;
BOOL FNGLOBAL wfxCmp
(
LPWAVEFORMATEX pwfxSrc,
LPWAVEFORMATEX pwfxDst
)
{
DWORD dwBufferSize;
if(pwfxSrc->wFormatTag != pwfxDst->wFormatTag)
{
//
// Hmm... Format tags are different.
//
return FALSE;
}
dwBufferSize = SIZEOFWAVEFORMAT(pwfxSrc);
if(dwBufferSize != (DWORD)SIZEOFWAVEFORMAT(pwfxDst))
{
return FALSE;
}
//
// Note: Not using _fmemcmp since this *has* to work across segments
// Which means with huge pointers. _fmemset does not use
// huge pointers w/ medium model, nor does it ever use it w/
// intrinsic version.
//
return (mem_cmp((LPBYTE)pwfxSrc,(LPBYTE)pwfxDst,dwBufferSize));
} // wfxCmp()
//--------------------------------------------------------------------------;
//
// void GetFormatString
//
// Description:
// Gets a string representation for the given format.
//
// Arguments:
// LPSTR pszFormat: Buffer to store the string in.
//
// LPWAVEFORMATEX pwfx: The format in question.
//
// DWORD cbSize: Size (in bytes) of the string buffer.
//
// Return (void):
//
// History:
// 11/30/93 Fwong Doing this function one more time!!
//
//--------------------------------------------------------------------------;
void FNGLOBAL GetFormatName
(
LPSTR pszFormat,
LPWAVEFORMATEX pwfx,
DWORD cbSize
)
{
ACMFORMATDETAILS afd;
ACMFORMATTAGDETAILS aftd;
MMRESULT mmr;
DWORD dw;
char szFormat[MAXFMTSTR];
dw = SIZEOFWAVEFORMAT(pwfx);
aftd.cbStruct = sizeof(ACMFORMATTAGDETAILS);
aftd.dwFormatTagIndex = 0L;
aftd.dwFormatTag = (DWORD)pwfx->wFormatTag;
aftd.fdwSupport = 0L;
mmr = acmFormatTagDetails(NULL,&aftd,ACM_FORMATTAGDETAILSF_FORMATTAG);
if(MMSYSERR_NOERROR != mmr)
{
pszFormat[0] = 0;
return;
}
afd.cbStruct = sizeof(ACMFORMATDETAILS);
afd.dwFormatIndex = 0L;
afd.dwFormatTag = (DWORD)pwfx->wFormatTag;
afd.fdwSupport = 0L;
afd.pwfx = pwfx;
afd.cbwfx = dw;
mmr = acmFormatDetails(NULL,&afd,ACM_FORMATDETAILSF_FORMAT);
if(MMSYSERR_NOERROR != mmr)
{
pszFormat[0] = 0;
return;
}
wsprintf(szFormat,"%s %s",(LPSTR)aftd.szFormatTag,(LPSTR)afd.szFormat);
dw = (DWORD)(lstrlen(szFormat)+1);
dw = min(dw,cbSize);
lstrcpyn(pszFormat,szFormat,(int)dw);
} // GetFormatName()
//--------------------------------------------------------------------------;
//
// BOOL FormatFlag_To_Format
//
// Description:
// Returns a standard PCM format from a given format flag.
// Format flags are based on WAVEXCAPS.
//
// Arguments:
// DWORD dwMask: Format Mask.
//
// LPPCMWAVEFORMAT ppcmwf: Buffer for PCM wave format.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 12/01/93 Fwong Re-done for WaveTest.
//
//--------------------------------------------------------------------------;
BOOL FNGLOBAL FormatFlag_To_Format
(
DWORD dwMask,
LPPCMWAVEFORMAT ppcmwf
)
{
LPWAVEFORMATEX pwfx;
if(0 == (dwMask & VALID_FORMAT_FLAGS))
{
//
// Not valid format flag!!
//
return FALSE;
}
pwfx = (LPWAVEFORMATEX)ppcmwf;
pwfx->wFormatTag = WAVE_FORMAT_PCM;
pwfx->nSamplesPerSec = 11025;
for(;dwMask & 0xfffffff0;dwMask /= 0x10)
{
pwfx->nSamplesPerSec *= 2;
}
switch (dwMask)
{
case WAVE_FORMAT_1M08:
pwfx->nChannels = 1;
pwfx->wBitsPerSample = 8;
break;
case WAVE_FORMAT_1S08:
pwfx->nChannels = 2;
pwfx->wBitsPerSample = 8;
break;
case WAVE_FORMAT_1M16:
pwfx->nChannels = 1;
pwfx->wBitsPerSample = 16;
break;
case WAVE_FORMAT_1S16:
pwfx->nChannels = 2;
pwfx->wBitsPerSample = 16;
break;
}
//
// Note: This may not work with 12 bit samples
// if they're done pairwise...
//
pwfx->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8;
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
} // FormatFlag_To_Format()
//--------------------------------------------------------------------------;
//
// void GetWaveInDriverName
//
// Description:
// Given a device ID, retrieves a driver name.
//
// Arguments:
// UINT uDeviceID: Device ID.
//
// LPSTR pszDriverName: Buffer to store driver name.
//
// DWORD cbSize: Size (in bytes) of buffer.
//
// Return (void):
//
// History:
// 02/18/94 Fwong Another random thing.
//
//--------------------------------------------------------------------------;
void FNGLOBAL GetWaveOutDriverName
(
UINT uDeviceID,
LPSTR pszDriverName,
DWORD cbSize
)
{
WAVEOUTCAPS woc;
MMRESULT mmr;
DWORD dw;
mmr = waveOutGetDevCaps(uDeviceID,&woc,sizeof(WAVEOUTCAPS));
dw = (DWORD)(lstrlen(woc.szPname)+1);
dw = min(dw,cbSize);
lstrcpyn(pszDriverName,woc.szPname,(int)dw);
} // GetWaveOutDriverName()
//--------------------------------------------------------------------------;
//
// void GetWaveOutDriverName
//
// Description:
// Given a device ID, retrieves a driver name.
//
// Arguments:
// UINT uDeviceID: Device ID.
//
// LPSTR pszDriverName: Buffer to store driver name.
//
// DWORD cbSize: Size (in bytes) of buffer.
//
// Return (void):
//
// History:
// 02/18/94 Fwong Another random thing.
//
//--------------------------------------------------------------------------;
void FNGLOBAL GetWaveInDriverName
(
UINT uDeviceID,
LPSTR pszDriverName,
DWORD cbSize
)
{
WAVEINCAPS wic;
MMRESULT mmr;
DWORD dw;
mmr = waveInGetDevCaps(uDeviceID,&wic,sizeof(WAVEINCAPS));
dw = (DWORD)(lstrlen(wic.szPname)+1);
dw = min(dw,cbSize);
lstrcpyn(pszDriverName,wic.szPname,(int)dw);
} // GetWaveInDriverName()
//--------------------------------------------------------------------------;
//
// LRESULT FormatEnumCB
//
// Description:
// Callback for enumerating formats.
//
// Arguments:
// HACMDRIVERID hadid: Handle to ACM driver.
//
// LPACMFORMATDETAILS pafd: Pointer to info structure.
//
// DWORD dwInstance: In our case, pointer to ENUMTYPE structure.
//
// DWORD fdwSupport: from API call.
//
// Return (LRESULT):
// FALSE if finished enumerating, TRUE otherwise.
//
// History:
// 07/05/93 Fwong For easy enumeration of ACM's format.
// 08/01/93 Fwong Logic changed to match Window's Enum.
//
//--------------------------------------------------------------------------;
BOOL FNEXPORT FormatEnumCB
(
HACMDRIVERID hadid,
LPACMFORMATDETAILS pafd,
DWORD dwInstance,
DWORD fdwSupport
)
{
LPENUMTYPE pet = (LPENUMTYPE)(dwInstance);
if(pet->dwTarget == pet->dwCount)
{
//
// Keep count accurate and stop enumerating.
//
(pet->dwCount)++;
return (FALSE);
}
(pet->dwCount)++;
return (TRUE);
} // FormatEnumCB()
//--------------------------------------------------------------------------;
//
// DWORD GetNumFormats
//
// Description:
// This funtion returns the number of standard formats supported by
// driver for all format tags.
//
// Arguments:
// None.
//
// Return (DWORD):
// The actual number of formats.
//
// History:
// 09/08/93 Fwong Generalizing to include all tags.
//
//--------------------------------------------------------------------------;
DWORD FNGLOBAL GetNumFormats
(
void
)
{
ENUMTYPE et;
ACMFORMATDETAILS afd;
MMRESULT mmr;
LPWAVEFORMATEX pwfx;
HGLOBAL hmem;
DWORD dwMaxSize;
mmr = acmMetrics(NULL,ACM_METRIC_MAX_SIZE_FORMAT,&dwMaxSize);
if(MMSYSERR_NOERROR != mmr)
{
return 0L;
}
hmem = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,dwMaxSize);
if(NULL == hmem)
{
//
// GlobalAlloc failed...
//
return 0L;
}
pwfx = (LPWAVEFORMATEX)GlobalLock(hmem);
et.dwCount = 0L;
et.dwTarget = (DWORD)(-1);
afd.cbStruct = sizeof(afd);
afd.pwfx = pwfx;
afd.cbwfx = dwMaxSize;
afd.pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN;
afd.fdwSupport = 0L;
mmr = acmFormatEnum(NULL,&afd,FormatEnumCB,(DWORD)(LPENUMTYPE)&et,0L);
if(MMSYSERR_NOERROR != mmr)
{
et.dwCount = 0L;
}
//
// Cleaning up...
//
GlobalUnlock(hmem);
GlobalFree(hmem);
return (et.dwCount);
} // GetNumFormats()
//--------------------------------------------------------------------------;
//
// BOOL GetFormat
//
// Description:
// This function returns the wave format according to the index.
//
// Arguments:
// LPWAVEFORMATEX pwfx: Return buffer for format.
//
// DWORD cbwfx: Size of format.
//
// DWORD dwIndex: Index to enumerate to.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 09/08/93 Fwong Generalizing to include all tags.
//
//--------------------------------------------------------------------------;
BOOL FNGLOBAL GetFormat
(
LPWAVEFORMATEX pwfx,
DWORD cbwfx,
DWORD dwIndex
)
{
ENUMTYPE et;
ACMFORMATDETAILS afd;
MMRESULT mmr;
HGLOBAL hmem;
DWORD dwMaxSize;
LPWAVEFORMATEX pwfxTemp;
mmr = acmMetrics(NULL,ACM_METRIC_MAX_SIZE_FORMAT,&dwMaxSize);
if(MMSYSERR_NOERROR != mmr)
{
//
// acmMetrics failed....
//
return FALSE;
}
hmem = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,dwMaxSize);
if(NULL == hmem)
{
//
// GlobalAlloc failed...
//
return (FALSE);
}
pwfxTemp = GlobalLock(hmem);
et.dwCount = 0L;
et.dwTarget = dwIndex;
afd.cbStruct = sizeof(afd);
afd.pwfx = pwfxTemp;
afd.cbwfx = dwMaxSize;
afd.pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN;
afd.fdwSupport = 0L;
mmr = acmFormatEnum(NULL,&afd,FormatEnumCB,(DWORD)(LPENUMTYPE)&et,0L);
if(MMSYSERR_NOERROR != mmr)
{
GlobalUnlock(hmem);
GlobalFree(hmem);
return (FALSE);
}
//
// Cleaning up...
//
dwMaxSize = SIZEOFWAVEFORMAT(pwfxTemp);
if(dwMaxSize > cbwfx)
{
//
// We don't have enough room?!
//
GlobalUnlock(hmem);
GlobalFree(hmem);
return (FALSE);
}
wfxCpy(pwfx,pwfxTemp);
GlobalUnlock(hmem);
GlobalFree(hmem);
return (TRUE);
} // GetFormatNumber()