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.
1810 lines
47 KiB
1810 lines
47 KiB
/////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
|
|
//
|
|
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
|
|
//
|
|
// Other brand and product names used herein are trademarks of their respective owners.
|
|
//
|
|
// The entire program and user interface including the structure, sequence, selection,
|
|
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
|
|
// by "1" and "2," and each dialog message are protected by copyrights registered in
|
|
// the United States and by international treaties.
|
|
//
|
|
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
|
|
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
|
|
//
|
|
// Active Voice Corporation
|
|
// Seattle, Washington
|
|
// USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////
|
|
// acm.c - audio compression manager functions
|
|
////
|
|
|
|
#include "winlocal.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "acm.h"
|
|
#include <msacm.h>
|
|
|
|
#include "loadlib.h"
|
|
|
|
// On some Win31 and WinNT systems, the audio compresion manager
|
|
// is not installed. Therefore, we use a thunking layer to more
|
|
// gracefully handle this situation. See acmthunk.c for details
|
|
//
|
|
#ifdef ACMTHUNK
|
|
#include "acmthunk.h"
|
|
#endif
|
|
|
|
#ifdef AVPCM
|
|
#include "pcm.h"
|
|
#endif
|
|
#include "mem.h"
|
|
#include "str.h"
|
|
#include "trace.h"
|
|
|
|
////
|
|
// private definitions
|
|
////
|
|
|
|
// acm control struct
|
|
//
|
|
typedef struct ACM
|
|
{
|
|
DWORD dwVersion;
|
|
HINSTANCE hInst;
|
|
HTASK hTask;
|
|
DWORD dwFlags;
|
|
UINT nLastError;
|
|
#ifdef AVPCM
|
|
HPCM hPcm;
|
|
#endif
|
|
LPWAVEFORMATEX lpwfxSrc;
|
|
LPWAVEFORMATEX lpwfxInterm1;
|
|
LPWAVEFORMATEX lpwfxInterm2;
|
|
LPWAVEFORMATEX lpwfxDst;
|
|
HACMSTREAM hAcmStream1;
|
|
HACMSTREAM hAcmStream2;
|
|
HACMSTREAM hAcmStream3;
|
|
#ifdef ACMTHUNK
|
|
BOOL fAcmThunkInitialized;
|
|
#endif
|
|
} ACM, FAR *LPACM;
|
|
|
|
// acm driver control struct
|
|
//
|
|
typedef struct ACMDRV
|
|
{
|
|
HACM hAcm;
|
|
HINSTANCE hInstLib;
|
|
HACMDRIVERID hadid;
|
|
WORD wMid;
|
|
WORD wPid;
|
|
UINT nLastError;
|
|
DWORD dwFlags;
|
|
} ACMDRV, FAR *LPACMDRV;
|
|
|
|
// <dwFlags> values in ACMDRV
|
|
//
|
|
#define ACMDRV_REMOVEDRIVER 0x00001000
|
|
|
|
#ifdef _WIN32
|
|
#define ACM_VERSION_MIN 0x03320000
|
|
#else
|
|
#define ACM_VERSION_MIN 0x02000000
|
|
#endif
|
|
|
|
// <dwFlags> values in AcmStreamSize
|
|
//
|
|
#define ACM_SOURCE 0x00010000
|
|
#define ACM_DESTINATION 0x00020000
|
|
|
|
// helper functions
|
|
//
|
|
static LPACM AcmGetPtr(HACM hAcm);
|
|
static HACM AcmGetHandle(LPACM lpAcm);
|
|
static LPACMDRV AcmDrvGetPtr(HACMDRV hAcmDrv);
|
|
static HACMDRV AcmDrvGetHandle(LPACMDRV lpAcmDrv);
|
|
static HACMSTREAM WINAPI AcmStreamOpen(HACM hAcm, LPWAVEFORMATEX lpwfxSrc,
|
|
LPWAVEFORMATEX lpwfxDst, LPWAVEFILTER lpwfltr, DWORD dwFlags);
|
|
static int WINAPI AcmStreamClose(HACM hAcm, HACMSTREAM hAcmStream);
|
|
static long WINAPI AcmStreamSize(HACM hAcm, HACMSTREAM hAcmStream, long sizBuf, DWORD dwFlags);
|
|
static long WINAPI AcmStreamConvert(HACM hAcm, HACMSTREAM hAcmStream,
|
|
void _huge *hpBufSrc, long sizBufSrc,
|
|
void _huge *hpBufDst, long sizBufDst,
|
|
DWORD dwFlags);
|
|
BOOL CALLBACK AcmDriverLoadEnumCallback(HACMDRIVERID hadid,
|
|
DWORD dwInstance, DWORD fdwSupport);
|
|
|
|
////
|
|
// public functions
|
|
////
|
|
|
|
// AcmInit - initialize audio compression manager engine
|
|
// <dwVersion> (i) must be ACM_VERSION
|
|
// <hInst> (i) instance handle of calling module
|
|
// <dwFlags> (i) control flags
|
|
#ifdef AVPCM
|
|
// ACM_NOACM use internal pcm engine rather than acm
|
|
#endif
|
|
// return handle (NULL if error)
|
|
//
|
|
HACM DLLEXPORT WINAPI AcmInit(DWORD dwVersion, HINSTANCE hInst, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm = NULL;
|
|
|
|
#ifndef AVPCM
|
|
// turn off ACM_NOACM flag if not allowed
|
|
//
|
|
dwFlags &= ~ACM_NOACM;
|
|
#endif
|
|
|
|
if (dwVersion != ACM_VERSION)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hInst == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpAcm = (LPACM) MemAlloc(NULL, sizeof(ACM), 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
lpAcm->dwVersion = dwVersion;
|
|
lpAcm->hInst = hInst;
|
|
lpAcm->hTask = GetCurrentTask();
|
|
lpAcm->dwFlags = dwFlags;
|
|
lpAcm->nLastError = 0;
|
|
#ifdef AVPCM
|
|
lpAcm->hPcm = NULL;
|
|
#endif
|
|
lpAcm->lpwfxSrc = NULL;
|
|
lpAcm->lpwfxInterm1 = NULL;
|
|
lpAcm->lpwfxInterm2 = NULL;
|
|
lpAcm->lpwfxDst = NULL;
|
|
lpAcm->hAcmStream1 = NULL;
|
|
lpAcm->hAcmStream2 = NULL;
|
|
lpAcm->hAcmStream3 = NULL;
|
|
#ifdef ACMTHUNK
|
|
lpAcm->fAcmThunkInitialized = FALSE;
|
|
|
|
if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
// initialize acm thunking layer
|
|
//
|
|
if (!acmThunkInitialize())
|
|
{
|
|
#ifdef AVPCM
|
|
fSuccess = TraceFALSE(NULL);
|
|
#else
|
|
// NOTE: this is not considered an error
|
|
//
|
|
fSuccess = TraceTRUE(NULL);
|
|
|
|
// failure means we cannot call any acm functions
|
|
//
|
|
lpAcm->dwFlags |= ACM_NOACM;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// remember so we can shut down later
|
|
//
|
|
lpAcm->fAcmThunkInitialized = TRUE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 0 // for testing
|
|
lpAcm->dwFlags |= ACM_NOACM;
|
|
#endif
|
|
if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
// verify minimum acm version
|
|
//
|
|
if (acmGetVersion() < ACM_VERSION_MIN)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
// initialize PCM engine
|
|
//
|
|
if ((lpAcm->hPcm = PcmInit(PCM_VERSION, hInst, 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (!fSuccess || (dwFlags & ACM_QUERY))
|
|
{
|
|
if (lpAcm != NULL && AcmTerm(AcmGetHandle(lpAcm)) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
else
|
|
lpAcm = NULL;
|
|
}
|
|
|
|
return fSuccess ? AcmGetHandle(lpAcm) : NULL;
|
|
}
|
|
|
|
// AcmTerm - shut down audio compression manager engine
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI AcmTerm(HACM hAcm)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (AcmConvertTerm(hAcm) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// $FIXUP - call to acmThunkTerminate is disabled so that AcmInit/AcmTerm
|
|
// can be called mutltiple times. This means the array of acm function
|
|
// pointers is not freed and FreeLibrary is not called on msacm.dll
|
|
//
|
|
#if 0
|
|
#ifdef ACMTHUNK
|
|
// shut down acm thunking layer
|
|
//
|
|
else if (lpAcm->fAcmThunkInitialized && !acmThunkTerminate())
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->fAcmThunkInitialized = FALSE, FALSE)
|
|
;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef AVPCM
|
|
// shut down pcm engine
|
|
//
|
|
else if (lpAcm->hPcm != NULL && PcmTerm(lpAcm->hPcm) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->hPcm = NULL, FALSE)
|
|
;
|
|
#endif
|
|
else if ((lpAcm = MemFree(NULL, lpAcm)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// AcmFormatGetSizeMax - get size of largest acm WAVEFORMATEX struct
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
//
|
|
// return size of largest format struct, -1 if error
|
|
//
|
|
int DLLEXPORT WINAPI AcmFormatGetSizeMax(HACM hAcm)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm = NULL;
|
|
DWORD dwSizeMax = 0;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
dwSizeMax = sizeof(WAVEFORMATEX);
|
|
#endif
|
|
// query largest format size
|
|
//
|
|
else if ((lpAcm->nLastError = acmMetrics(NULL,
|
|
ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID) &dwSizeMax)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmMetrics failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
|
|
return fSuccess ? (int) dwSizeMax : -1;
|
|
}
|
|
|
|
// AcmFormatChoose - choose audio format from dialog box
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hwndOwner> (i) owner of dialog box
|
|
// NULL no owner
|
|
// <lpszTitle> (i) title of the dialog box
|
|
// NULL use default title ("Sound Selection")
|
|
// <lpwfx> (i) initialize dialog with this format
|
|
// NULL no initial format
|
|
// <dwFlags> (i) control flags
|
|
// ACM_FORMATPLAY restrict choices to playback formats
|
|
// ACM_FORMATRECORD restrict choices to recording formats
|
|
// return pointer to chosen format, NULL if error or none chosen
|
|
//
|
|
// NOTE: the format structure returned is dynamically allocated.
|
|
// Use WavFormatFree() to free the buffer.
|
|
//
|
|
LPWAVEFORMATEX DLLEXPORT WINAPI AcmFormatChooseEx(HACM hAcm,
|
|
HWND hwndOwner, LPCTSTR lpszTitle, LPWAVEFORMATEX lpwfx, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
ACMFORMATCHOOSE afc;
|
|
int nFormatSize = 0;
|
|
int nFormatSizeMax;
|
|
LPWAVEFORMATEX lpwfxNew = NULL;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// make sure current format is valid
|
|
//
|
|
else if (lpwfx != NULL && !WavFormatIsValid(lpwfx))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// calc how big is the initial format struct
|
|
//
|
|
else if (lpwfx != NULL && (nFormatSize = WavFormatGetSize(lpwfx)) <= 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// calc how big is the largest format struct in the acm
|
|
//
|
|
else if ((nFormatSizeMax = AcmFormatGetSizeMax(hAcm)) <= 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// alloc a new format struct that is sure to be big enough
|
|
//
|
|
else if ((lpwfxNew = WavFormatAlloc((WORD)
|
|
max(nFormatSize, nFormatSizeMax))) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
// no standard dialog available; just return a valid format
|
|
//
|
|
if (lpwfx == NULL && WavFormatPcm(-1, -1, -1, lpwfxNew) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
else if (lpwfx != NULL && WavFormatCopy(lpwfxNew, lpwfx) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
// initialize the format struct
|
|
//
|
|
MemSet(&afc, 0, sizeof(afc));
|
|
|
|
afc.cbStruct = sizeof(afc);
|
|
afc.fdwStyle = 0;
|
|
afc.hwndOwner = hwndOwner;
|
|
afc.pwfx = lpwfxNew;
|
|
afc.cbwfx = WavFormatGetSize(lpwfxNew);
|
|
afc.pszTitle = lpszTitle;
|
|
afc.szFormatTag[0] = '\0';
|
|
afc.szFormat[0] = '\0';
|
|
afc.pszName = NULL;
|
|
afc.cchName = 0;
|
|
afc.fdwEnum = 0;
|
|
afc.pwfxEnum = NULL;
|
|
afc.hInstance = NULL;
|
|
afc.pszTemplateName = NULL;
|
|
afc.lCustData = 0L;
|
|
afc.pfnHook = NULL;
|
|
|
|
if (lpwfx != NULL)
|
|
{
|
|
// supply initial format to dialog if possible
|
|
//
|
|
afc.fdwStyle |= ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
|
|
|
|
if (WavFormatCopy(lpwfxNew, lpwfx) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// restrict choices if necessary
|
|
//
|
|
if (dwFlags & ACM_FORMATPLAY)
|
|
afc.fdwEnum |= ACM_FORMATENUMF_OUTPUT;
|
|
if (dwFlags & ACM_FORMATRECORD)
|
|
afc.fdwEnum |= ACM_FORMATENUMF_INPUT;
|
|
|
|
// do the dialog box, fill in lpwfxNew with chosen format
|
|
//
|
|
if ((lpAcm->nLastError = acmFormatChoose(&afc)) != 0)
|
|
{
|
|
if (lpAcm->nLastError == ACMERR_CANCELED)
|
|
{
|
|
fSuccess = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmFormatChoose failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fSuccess && lpwfxNew != NULL)
|
|
{
|
|
if (WavFormatFree(lpwfxNew) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? lpwfxNew : NULL;
|
|
}
|
|
|
|
// AcmFormatSuggest - suggest a new format
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <lpwfxSrc> (i) source format
|
|
// <nFormatTag> (i) suggested format must match this format tag
|
|
// -1 suggestion need not match
|
|
// <nSamplesPerSec> (i) suggested format must match this sample rate
|
|
// -1 suggestion need not match
|
|
// <nBitsPerSample> (i) suggested format must match this sample size
|
|
// -1 suggestion need not match
|
|
// <nChannels> (i) suggested format must match this channels
|
|
// -1 suggestion need not match
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return pointer to suggested format, NULL if error
|
|
//
|
|
// NOTE: the format structure returned is dynamically allocated.
|
|
// Use WavFormatFree() to free the buffer.
|
|
//
|
|
LPWAVEFORMATEX DLLEXPORT WINAPI AcmFormatSuggestEx(HACM hAcm,
|
|
LPWAVEFORMATEX lpwfxSrc, long nFormatTag, long nSamplesPerSec,
|
|
int nBitsPerSample, int nChannels, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
int nFormatSize = 0;
|
|
int nFormatSizeMax;
|
|
LPWAVEFORMATEX lpwfxNew = NULL;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// make sure source format is valid
|
|
//
|
|
else if (!WavFormatIsValid(lpwfxSrc))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// calc how big is the source format struct
|
|
//
|
|
else if ((nFormatSize = WavFormatGetSize(lpwfxSrc)) <= 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// calc how big is the largest format struct in the acm
|
|
//
|
|
else if ((nFormatSizeMax = AcmFormatGetSizeMax(hAcm)) <= 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// alloc a new format struct that is sure to be big enough
|
|
//
|
|
else if ((lpwfxNew = WavFormatAlloc((WORD)
|
|
max(nFormatSize, nFormatSizeMax))) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// copy source format to new format
|
|
//
|
|
else if (WavFormatCopy(lpwfxNew, lpwfxSrc) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
DWORD dwFlagsSuggest = 0;
|
|
|
|
// restrict suggestions if necessary
|
|
//
|
|
if (nFormatTag != -1)
|
|
{
|
|
lpwfxNew->wFormatTag = (WORD) nFormatTag;
|
|
dwFlagsSuggest |= ACM_FORMATSUGGESTF_WFORMATTAG;
|
|
}
|
|
|
|
if (nSamplesPerSec != -1)
|
|
{
|
|
lpwfxNew->nSamplesPerSec = (DWORD) nSamplesPerSec;
|
|
dwFlagsSuggest |= ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
|
|
}
|
|
|
|
if (nBitsPerSample != -1)
|
|
{
|
|
lpwfxNew->wBitsPerSample = (WORD) nBitsPerSample;
|
|
dwFlagsSuggest |= ACM_FORMATSUGGESTF_WBITSPERSAMPLE;
|
|
}
|
|
|
|
if (nChannels != -1)
|
|
{
|
|
lpwfxNew->nChannels = (WORD) nChannels;
|
|
dwFlagsSuggest |= ACM_FORMATSUGGESTF_NCHANNELS;
|
|
}
|
|
|
|
if ((lpAcm->nLastError = acmFormatSuggest(NULL, lpwfxSrc,
|
|
lpwfxNew, max(nFormatSize, nFormatSizeMax), dwFlagsSuggest)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmFormatSuggest failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
// make a suggested format based on source
|
|
// $FIXUP - this code should be in pcm.c
|
|
//
|
|
if (nFormatTag != -1)
|
|
lpwfxNew->wFormatTag = (WORD) nFormatTag;
|
|
else
|
|
lpwfxNew->wFormatTag = WAVE_FORMAT_PCM;
|
|
|
|
if (nSamplesPerSec != -1)
|
|
lpwfxNew->nSamplesPerSec = (DWORD) nSamplesPerSec;
|
|
else if (lpwfxNew->nSamplesPerSec < 8000)
|
|
lpwfxNew->nSamplesPerSec = 6000;
|
|
else if (lpwfxNew->nSamplesPerSec < 11025)
|
|
lpwfxNew->nSamplesPerSec = 8000;
|
|
else if (lpwfxNew->nSamplesPerSec < 22050)
|
|
lpwfxNew->nSamplesPerSec = 11025;
|
|
else if (lpwfxNew->nSamplesPerSec < 44100)
|
|
lpwfxNew->nSamplesPerSec = 22050;
|
|
else
|
|
lpwfxNew->nSamplesPerSec = 44100;
|
|
|
|
if (nBitsPerSample != -1)
|
|
lpwfxNew->wBitsPerSample = (WORD) nBitsPerSample;
|
|
else if (lpwfxNew->wBitsPerSample < 16)
|
|
lpwfxNew->wBitsPerSample = 8;
|
|
else
|
|
lpwfxNew->wBitsPerSample = 16;
|
|
|
|
if (nChannels != -1)
|
|
lpwfxNew->nChannels = (WORD) nChannels;
|
|
else
|
|
lpwfxNew->nChannels = 1;
|
|
|
|
// recalculate nBlockAlign and nAvgBytesPerSec
|
|
//
|
|
if (WavFormatPcm(lpwfxNew->nSamplesPerSec,
|
|
lpwfxNew->wBitsPerSample,
|
|
lpwfxNew->nChannels, lpwfxNew) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#endif
|
|
if (!fSuccess && lpwfxNew != NULL)
|
|
{
|
|
if (WavFormatFree(lpwfxNew) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? lpwfxNew : NULL;
|
|
}
|
|
|
|
// AcmFormatGetText - get text describing the specified format
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <lpwfx> (i) format
|
|
// <lpszText> (o) buffer to hold text
|
|
// <sizText> (i) size of buffer, in characters
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI AcmFormatGetText(HACM hAcm, LPWAVEFORMATEX lpwfx,
|
|
LPTSTR lpszText, int sizText, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
TCHAR szFormat[ACMFORMATDETAILS_FORMAT_CHARS];
|
|
TCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
|
|
|
|
//
|
|
// We have to initialize szFormatTag
|
|
//
|
|
_tcscpy( szFormatTag, _T("") );
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// make sure format is valid
|
|
//
|
|
else if (!WavFormatIsValid(lpwfx))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpszText == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (fSuccess && !(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
ACMFORMATTAGDETAILS atd;
|
|
|
|
// initialize the details struct
|
|
//
|
|
MemSet(&atd, 0, sizeof(atd));
|
|
|
|
atd.cbStruct = sizeof(atd);
|
|
atd.dwFormatTagIndex = 0;
|
|
atd.dwFormatTag = lpwfx->wFormatTag;
|
|
atd.cbFormatSize = WavFormatGetSize(lpwfx);
|
|
atd.fdwSupport = 0;
|
|
atd.cStandardFormats = 0;
|
|
atd.szFormatTag[0] = '\0';
|
|
|
|
// get format tag details
|
|
//
|
|
if ((lpAcm->nLastError = acmFormatTagDetails(NULL,
|
|
&atd, ACM_FORMATTAGDETAILSF_FORMATTAG)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmFormatTagDetails failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
|
|
else
|
|
StrNCpy(szFormatTag, atd.szFormatTag, SIZEOFARRAY(szFormatTag));
|
|
}
|
|
#ifdef AVPCM
|
|
if (fSuccess && (lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
if (lpwfx->wFormatTag != WAVE_FORMAT_PCM)
|
|
StrNCpy(szFormatTag, TEXT("*** Non-PCM ***"), SIZEOFARRAY(szFormatTag));
|
|
else
|
|
StrNCpy(szFormatTag, TEXT("PCM"), SIZEOFARRAY(szFormatTag));
|
|
}
|
|
#endif
|
|
if (fSuccess && !(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
ACMFORMATDETAILS afd;
|
|
|
|
// initialize the details struct
|
|
//
|
|
MemSet(&afd, 0, sizeof(afd));
|
|
|
|
afd.cbStruct = sizeof(afd);
|
|
afd.dwFormatIndex = 0;
|
|
afd.dwFormatTag = lpwfx->wFormatTag;
|
|
afd.fdwSupport = 0;
|
|
afd.pwfx = lpwfx;
|
|
afd.cbwfx = WavFormatGetSize(lpwfx);
|
|
afd.szFormat[0] = '\0';
|
|
|
|
// get format details
|
|
//
|
|
if ((lpAcm->nLastError = acmFormatDetails(NULL,
|
|
&afd, ACM_FORMATDETAILSF_FORMAT)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmFormatDetails failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
|
|
else
|
|
StrNCpy(szFormat, afd.szFormat, SIZEOFARRAY(szFormat));
|
|
}
|
|
#ifdef AVPCM
|
|
if (fSuccess && (lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
TCHAR szTemp[64];
|
|
|
|
wsprintf(szTemp, TEXT("%d.%03d kHz, %d Bit, %s"),
|
|
(int) lpwfx->nSamplesPerSec / 1000,
|
|
(int) lpwfx->nSamplesPerSec % 1000,
|
|
(int) lpwfx->wBitsPerSample,
|
|
(LPTSTR) (lpwfx->nChannels == 1 ? TEXT("Mono") : TEXT("Stereo")));
|
|
|
|
StrNCpy(szFormat, szTemp, SIZEOFARRAY(szFormat));
|
|
}
|
|
#endif
|
|
// fill output buffer with results
|
|
//
|
|
if (fSuccess)
|
|
{
|
|
StrNCpy(lpszText, szFormatTag, sizText);
|
|
StrNCat(lpszText, TEXT("\t"), sizText);
|
|
StrNCat(lpszText, szFormat, sizText);
|
|
}
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// AcmConvertInit - initialize acm conversion engine
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <lpwfxSrc> (i) pointer to source WAVEFORMATEX struct
|
|
// <lpwfxDst> (i) pointer to destination WAVEFORMATEX struct
|
|
// <lpwfltr> (i) pointer to WAVEFILTER struct
|
|
// NULL reserved; must be NULL
|
|
// <dwFlags> (i) control flags
|
|
// ACM_NONREALTIME realtime conversion conversion not required
|
|
// ACM_QUERY return 0 if conversion would be supported
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI AcmConvertInit(HACM hAcm, LPWAVEFORMATEX lpwfxSrc,
|
|
LPWAVEFORMATEX lpwfxDst, LPWAVEFILTER lpwfltr, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (AcmConvertTerm(hAcm) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// make sure formats are valid
|
|
//
|
|
else if (!WavFormatIsValid(lpwfxSrc))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!WavFormatIsValid(lpwfxDst))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// save a copy of source and destination formats
|
|
//
|
|
else if ((lpAcm->lpwfxSrc = WavFormatDup(lpwfxSrc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpAcm->lpwfxDst = WavFormatDup(lpwfxDst)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
// PCM source --> PCM destination
|
|
//
|
|
if (lpwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
|
|
lpwfxDst->wFormatTag == WAVE_FORMAT_PCM)
|
|
{
|
|
// open the acm conversion stream
|
|
//
|
|
if ((lpAcm->hAcmStream1 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpwfxSrc, lpwfxDst, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
// non-PCM source --> non-PCM destination
|
|
//
|
|
else if (lpwfxSrc->wFormatTag != WAVE_FORMAT_PCM &&
|
|
lpwfxDst->wFormatTag != WAVE_FORMAT_PCM)
|
|
{
|
|
// find a suitable intermediate PCM source format
|
|
//
|
|
if ((lpAcm->lpwfxInterm1 = AcmFormatSuggest(hAcm,
|
|
lpwfxSrc, WAVE_FORMAT_PCM, -1, -1, -1, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the first acm conversion stream
|
|
//
|
|
else if ((lpAcm->hAcmStream1 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxSrc, lpAcm->lpwfxInterm1, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// find a suitable intermediate PCM destination format
|
|
//
|
|
else if ((lpAcm->lpwfxInterm2 = AcmFormatSuggest(hAcm,
|
|
lpwfxDst, WAVE_FORMAT_PCM, -1, -1, -1, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the second acm conversion stream
|
|
//
|
|
else if (WavFormatCmp(lpAcm->lpwfxInterm1,
|
|
lpAcm->lpwfxInterm2) == 0 &&
|
|
(lpAcm->hAcmStream2 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxInterm1, lpAcm->lpwfxDst, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the second acm conversion stream
|
|
//
|
|
else if (WavFormatCmp(lpAcm->lpwfxInterm1,
|
|
lpAcm->lpwfxInterm2) != 0 &&
|
|
(lpAcm->hAcmStream2 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxInterm1, lpAcm->lpwfxInterm2, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the third acm conversion stream if necessary
|
|
//
|
|
else if (WavFormatCmp(lpAcm->lpwfxInterm1,
|
|
lpAcm->lpwfxInterm2) != 0 &&
|
|
(lpAcm->hAcmStream3 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxInterm2, lpAcm->lpwfxDst, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
// non-PCM source --> PCM destination
|
|
//
|
|
else if (lpwfxSrc->wFormatTag != WAVE_FORMAT_PCM &&
|
|
lpwfxDst->wFormatTag == WAVE_FORMAT_PCM)
|
|
{
|
|
// find a suitable intermediate PCM format
|
|
//
|
|
if ((lpAcm->lpwfxInterm1 = AcmFormatSuggest(hAcm,
|
|
lpwfxSrc, WAVE_FORMAT_PCM, -1, -1, -1, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the first acm conversion stream
|
|
//
|
|
else if ((lpAcm->hAcmStream1 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxSrc, lpAcm->lpwfxInterm1, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the second acm conversion stream if necessary
|
|
//
|
|
else if (WavFormatCmp(lpAcm->lpwfxInterm1,
|
|
lpAcm->lpwfxDst) != 0 &&
|
|
(lpAcm->hAcmStream2 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxInterm1, lpAcm->lpwfxDst, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
// PCM source --> non-PCM destination
|
|
//
|
|
else if (lpwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
|
|
lpwfxDst->wFormatTag != WAVE_FORMAT_PCM)
|
|
{
|
|
// find a suitable intermediate PCM format
|
|
//
|
|
if ((lpAcm->lpwfxInterm1 = AcmFormatSuggest(hAcm,
|
|
lpwfxDst, WAVE_FORMAT_PCM, -1, -1, -1, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the first acm conversion stream
|
|
//
|
|
else if ((lpAcm->hAcmStream1 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxSrc, lpAcm->lpwfxInterm1, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// open the second acm conversion stream
|
|
//
|
|
else if ((lpAcm->hAcmStream2 = AcmStreamOpen(AcmGetHandle(lpAcm),
|
|
lpAcm->lpwfxInterm1, lpAcm->lpwfxDst, NULL, dwFlags)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
// if we do not have the acm, we are limited to
|
|
// the sub-set of PCM formats handled by pcm.c
|
|
// $FIXUP - move this code to pcm.c
|
|
//
|
|
|
|
if (lpwfxSrc->wFormatTag != WAVE_FORMAT_PCM)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpwfxSrc->nChannels != 1)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpwfxSrc->nSamplesPerSec != 6000 &&
|
|
lpwfxSrc->nSamplesPerSec != 8000 &&
|
|
lpwfxSrc->nSamplesPerSec != 11025 &&
|
|
lpwfxSrc->nSamplesPerSec != 22050 &&
|
|
lpwfxSrc->nSamplesPerSec != 44100)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpwfxDst->wFormatTag != WAVE_FORMAT_PCM)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpwfxDst->nChannels != 1)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpwfxDst->nSamplesPerSec != 6000 &&
|
|
lpwfxDst->nSamplesPerSec != 8000 &&
|
|
lpwfxDst->nSamplesPerSec != 11025 &&
|
|
lpwfxDst->nSamplesPerSec != 22050 &&
|
|
lpwfxDst->nSamplesPerSec != 44100)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (!fSuccess || (dwFlags & ACM_QUERY))
|
|
{
|
|
if (AcmConvertTerm(hAcm) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// AcmConvertTerm - shut down acm conversion engine
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI AcmConvertTerm(HACM hAcm)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// close the acm conversion stream
|
|
//
|
|
else if (lpAcm->hAcmStream1 != NULL &&
|
|
AcmStreamClose(hAcm, lpAcm->hAcmStream1) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (lpAcm->hAcmStream1 = NULL, FALSE)
|
|
;
|
|
|
|
// close the acm conversion stream
|
|
//
|
|
else if (lpAcm->hAcmStream2 != NULL &&
|
|
AcmStreamClose(hAcm, lpAcm->hAcmStream2) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (lpAcm->hAcmStream2 = NULL, FALSE)
|
|
;
|
|
|
|
// close the acm conversion stream
|
|
//
|
|
else if (lpAcm->hAcmStream3 != NULL &&
|
|
AcmStreamClose(hAcm, lpAcm->hAcmStream3) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (lpAcm->hAcmStream3 = NULL, FALSE)
|
|
;
|
|
|
|
// free source and destination formats
|
|
//
|
|
else if (lpAcm->lpwfxSrc != NULL && WavFormatFree(lpAcm->lpwfxSrc) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->lpwfxSrc = NULL, FALSE)
|
|
;
|
|
|
|
else if (lpAcm->lpwfxInterm1 != NULL && WavFormatFree(lpAcm->lpwfxInterm1) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->lpwfxInterm1 = NULL, FALSE)
|
|
;
|
|
|
|
else if (lpAcm->lpwfxInterm2 != NULL && WavFormatFree(lpAcm->lpwfxInterm2) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->lpwfxInterm2 = NULL, FALSE)
|
|
;
|
|
|
|
else if (lpAcm->lpwfxDst != NULL && WavFormatFree(lpAcm->lpwfxDst) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->lpwfxDst = NULL, FALSE)
|
|
;
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// AcmConvertGetSizeSrc - calculate source buffer size
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <sizBufDst> (i) size of destination buffer in bytes
|
|
// return source buffer size, -1 if error
|
|
//
|
|
long DLLEXPORT WINAPI AcmConvertGetSizeSrc(HACM hAcm, long sizBufDst)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
//
|
|
// We should intialize local variable
|
|
long sizBufSrc = -1;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
if (lpAcm->hAcmStream1 == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (fSuccess && lpAcm->hAcmStream3 != NULL &&
|
|
(sizBufDst = AcmStreamSize(hAcm, lpAcm->hAcmStream3,
|
|
(DWORD) sizBufDst, ACM_DESTINATION)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess && lpAcm->hAcmStream2 != NULL &&
|
|
(sizBufDst = AcmStreamSize(hAcm, lpAcm->hAcmStream2,
|
|
(DWORD) sizBufDst, ACM_DESTINATION)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess &&
|
|
(sizBufSrc = AcmStreamSize(hAcm, lpAcm->hAcmStream1,
|
|
(DWORD) sizBufDst, ACM_DESTINATION)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
if ((sizBufSrc = PcmCalcSizBufSrc(lpAcm->hPcm, sizBufDst,
|
|
lpAcm->lpwfxSrc, lpAcm->lpwfxDst)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#endif
|
|
return fSuccess ? sizBufSrc : -1;
|
|
}
|
|
|
|
// AcmConvertGetSizeDst - calculate destination buffer size
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <sizBufSrc> (i) size of source buffer in bytes
|
|
// return destination buffer size, -1 if error
|
|
//
|
|
long DLLEXPORT WINAPI AcmConvertGetSizeDst(HACM hAcm, long sizBufSrc)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
//
|
|
// We should initialize the ocal variable
|
|
//
|
|
long sizBufDst = -1;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
if (lpAcm->hAcmStream1 == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (fSuccess && lpAcm->hAcmStream3 != NULL &&
|
|
(sizBufSrc = AcmStreamSize(hAcm, lpAcm->hAcmStream3,
|
|
(DWORD) sizBufSrc, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess && lpAcm->hAcmStream2 != NULL &&
|
|
(sizBufSrc = AcmStreamSize(hAcm, lpAcm->hAcmStream2,
|
|
(DWORD) sizBufSrc, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess &&
|
|
(sizBufDst = AcmStreamSize(hAcm, lpAcm->hAcmStream1,
|
|
(DWORD) sizBufSrc, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
if ((sizBufDst = PcmCalcSizBufDst(lpAcm->hPcm, sizBufSrc,
|
|
lpAcm->lpwfxSrc, lpAcm->lpwfxDst)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return fSuccess ? sizBufDst : -1;
|
|
}
|
|
|
|
// AcmConvert - convert wav data from one format to another
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hpBufSrc> (i) buffer containing bytes to reformat
|
|
// <sizBufSrc> (i) size of buffer in bytes
|
|
// <hpBufDst> (o) buffer to contain new format
|
|
// <sizBufDst> (i) size of buffer in bytes
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return count of bytes in destination buffer (-1 if error)
|
|
//
|
|
// NOTE: the destination buffer must be large enough to hold the result
|
|
//
|
|
long DLLEXPORT WINAPI AcmConvert(HACM hAcm,
|
|
void _huge *hpBufSrc, long sizBufSrc,
|
|
void _huge *hpBufDst, long sizBufDst,
|
|
DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
//
|
|
// We should initialize local variable
|
|
//
|
|
long cbDst = -1;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!(lpAcm->dwFlags & ACM_NOACM))
|
|
{
|
|
if (lpAcm->hAcmStream1 == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpAcm->hAcmStream2 == NULL)
|
|
{
|
|
if ((cbDst = AcmStreamConvert(hAcm, lpAcm->hAcmStream1,
|
|
hpBufSrc, sizBufSrc, hpBufDst, sizBufDst, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
|
|
else if (lpAcm->hAcmStream3 == NULL)
|
|
{
|
|
long sizBufInterm;
|
|
long cbInterm;
|
|
void _huge *hpBufInterm = NULL;
|
|
|
|
if ((sizBufInterm = AcmStreamSize(hAcm, lpAcm->hAcmStream1,
|
|
(DWORD) sizBufSrc, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (sizBufInterm == 0)
|
|
cbDst = 0; // nothing to do
|
|
|
|
else if ((hpBufInterm = (void _huge *) MemAlloc(NULL,
|
|
sizBufInterm, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((cbInterm = AcmStreamConvert(hAcm, lpAcm->hAcmStream1,
|
|
hpBufSrc, sizBufSrc, hpBufInterm, sizBufInterm, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((cbDst = AcmStreamConvert(hAcm, lpAcm->hAcmStream2,
|
|
hpBufInterm, cbInterm, hpBufDst, sizBufDst, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (hpBufInterm != NULL &&
|
|
(hpBufInterm = MemFree(NULL, hpBufInterm)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else // if (lpAcm->hAcmStream3 !== NULL)
|
|
{
|
|
long sizBufInterm1;
|
|
long cbInterm1;
|
|
void _huge *hpBufInterm1 = NULL;
|
|
long sizBufInterm2;
|
|
long cbInterm2;
|
|
void _huge *hpBufInterm2 = NULL;
|
|
|
|
if ((sizBufInterm1 = AcmStreamSize(hAcm, lpAcm->hAcmStream1,
|
|
(DWORD) sizBufSrc, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (sizBufInterm1 == 0)
|
|
cbDst = 0; // nothing to do
|
|
|
|
else if ((hpBufInterm1 = (void _huge *) MemAlloc(NULL,
|
|
sizBufInterm1, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((sizBufInterm2 = AcmStreamSize(hAcm, lpAcm->hAcmStream2,
|
|
(DWORD) sizBufInterm1, ACM_SOURCE)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if (sizBufInterm2 == 0)
|
|
cbDst = 0; // nothing to do
|
|
|
|
else if ((hpBufInterm2 = (void _huge *) MemAlloc(NULL,
|
|
sizBufInterm2, 0)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((cbInterm1 = AcmStreamConvert(hAcm, lpAcm->hAcmStream1,
|
|
hpBufSrc, sizBufSrc, hpBufInterm1, sizBufInterm1, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((cbInterm2 = AcmStreamConvert(hAcm, lpAcm->hAcmStream2,
|
|
hpBufInterm1, cbInterm1, hpBufInterm2, sizBufInterm2, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
else if ((cbDst = AcmStreamConvert(hAcm, lpAcm->hAcmStream3,
|
|
hpBufInterm2, cbInterm2, hpBufDst, sizBufDst, dwFlags)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (hpBufInterm1 != NULL &&
|
|
(hpBufInterm1 = MemFree(NULL, hpBufInterm1)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hpBufInterm2 != NULL &&
|
|
(hpBufInterm2 = MemFree(NULL, hpBufInterm2)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#ifdef AVPCM
|
|
else if (lpAcm->dwFlags & ACM_NOACM)
|
|
{
|
|
// perform the conversion
|
|
//
|
|
if ((cbDst = PcmConvert(lpAcm->hPcm,
|
|
hpBufSrc, sizBufSrc, lpAcm->lpwfxSrc,
|
|
hpBufDst, sizBufDst, lpAcm->lpwfxDst, 0)) < 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return fSuccess ? cbDst : -1;
|
|
}
|
|
|
|
// AcmDriverLoad - load an acm driver for use by this process
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <wMid> (i) manufacturer id
|
|
// <wPid> (i) product id
|
|
// <lpszDriver> (i) name of driver module
|
|
// <lpszDriverProc> (i) name of driver proc function
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return handle (NULL if error)
|
|
//
|
|
HACMDRV DLLEXPORT WINAPI AcmDriverLoad(HACM hAcm, WORD wMid, WORD wPid,
|
|
LPTSTR lpszDriver, LPSTR lpszDriverProc, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
LPACMDRV lpAcmDrv = NULL;
|
|
DRIVERPROC lpfnDriverProc;
|
|
ACMDRIVERENUMCB lpfnAcmDriverLoadEnumCallback;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpszDriver == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpszDriverProc == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpAcmDrv = (LPACMDRV) MemAlloc(NULL, sizeof(ACMDRV), 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
lpAcmDrv->hAcm = hAcm;
|
|
lpAcmDrv->hInstLib = NULL;
|
|
lpAcmDrv->hadid = NULL;
|
|
lpAcmDrv->wMid = wMid;
|
|
lpAcmDrv->wPid = wPid;
|
|
lpAcmDrv->nLastError = 0;
|
|
lpAcmDrv->dwFlags = 0;
|
|
|
|
if ((lpfnAcmDriverLoadEnumCallback = (ACMDRIVERENUMCB)
|
|
MakeProcInstance((FARPROC) AcmDriverLoadEnumCallback,
|
|
lpAcm->hInst)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// enumerate all drivers to see if specified driver is already loaded
|
|
//
|
|
else if ((lpAcmDrv->nLastError = acmDriverEnum(lpfnAcmDriverLoadEnumCallback, PtrToUlong(lpAcmDrv), 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmDriverEnum failed (%u)\n"),
|
|
(unsigned) lpAcmDrv->nLastError);
|
|
}
|
|
|
|
// if error or driver is already loaded, we are done
|
|
//
|
|
if (!fSuccess || lpAcmDrv->hadid != NULL)
|
|
;
|
|
|
|
// load the driver module if possible
|
|
//
|
|
else if ((lpAcmDrv->hInstLib = LoadLibraryPath(lpszDriver,
|
|
lpAcm->hInst, 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get address of driver proc function
|
|
//
|
|
else if ((lpfnDriverProc = (DRIVERPROC)
|
|
GetProcAddress(lpAcmDrv->hInstLib, lpszDriverProc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// add driver to list of available acm drivers
|
|
//
|
|
else if ((lpAcmDrv->nLastError = acmDriverAdd(&lpAcmDrv->hadid,
|
|
lpAcmDrv->hInstLib, (LPARAM) lpfnDriverProc, 0,
|
|
ACM_DRIVERADDF_FUNCTION | ACM_DRIVERADDF_LOCAL)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmDriverAdd failed (%u)\n"),
|
|
(unsigned) lpAcmDrv->nLastError);
|
|
}
|
|
|
|
// set flag so we know to call acmDriverRemove
|
|
//
|
|
else
|
|
lpAcmDrv->dwFlags |= ACMDRV_REMOVEDRIVER;
|
|
}
|
|
|
|
if (!fSuccess && lpAcmDrv != NULL &&
|
|
(lpAcmDrv = MemFree(NULL, lpAcmDrv)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? AcmDrvGetHandle(lpAcmDrv) : NULL;
|
|
}
|
|
|
|
// AcmDriverUnload - unload an acm driver
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hAcmDrv> (i) handle returned from AcmDriverLoad
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI AcmDriverUnload(HACM hAcm, HACMDRV hAcmDrv)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACMDRV lpAcmDrv;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpAcmDrv = AcmDrvGetPtr(hAcmDrv)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hAcm != lpAcmDrv->hAcm)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
// remove driver from acm if necessary
|
|
//
|
|
if ((lpAcmDrv->dwFlags & ACMDRV_REMOVEDRIVER) &&
|
|
lpAcmDrv->hadid != NULL &&
|
|
(lpAcmDrv->nLastError =
|
|
acmDriverRemove(lpAcmDrv->hadid, 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmDriverRemove failed (%u)\n"),
|
|
(unsigned) lpAcmDrv->nLastError);
|
|
}
|
|
else
|
|
lpAcmDrv->hadid = NULL;
|
|
|
|
// driver module no longer needed
|
|
//
|
|
if (lpAcmDrv->hInstLib != NULL)
|
|
{
|
|
FreeLibrary(lpAcmDrv->hInstLib);
|
|
lpAcmDrv->hInstLib = NULL;
|
|
}
|
|
|
|
if ((lpAcmDrv = MemFree(NULL, lpAcmDrv)) != NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
////
|
|
// helper functions
|
|
////
|
|
|
|
// AcmGetPtr - verify that acm handle is valid,
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// return corresponding acm pointer (NULL if error)
|
|
//
|
|
static LPACM AcmGetPtr(HACM hAcm)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = (LPACM) hAcm) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (IsBadWritePtr(lpAcm, sizeof(ACM)))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
#ifdef CHECKTASK
|
|
// make sure current task owns the acm handle
|
|
//
|
|
else if (lpAcm->hTask != GetCurrentTask())
|
|
fSuccess = TraceFALSE(NULL);
|
|
#endif
|
|
|
|
return fSuccess ? lpAcm : NULL;
|
|
}
|
|
|
|
// AcmGetHandle - verify that acm pointer is valid,
|
|
// <lpAcm> (i) pointer to ACM struct
|
|
// return corresponding acm handle (NULL if error)
|
|
//
|
|
static HACM AcmGetHandle(LPACM lpAcm)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HACM hAcm;
|
|
|
|
if ((hAcm = (HACM) lpAcm) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? hAcm : NULL;
|
|
}
|
|
|
|
// AcmDrvGetPtr - verify that acmdrv handle is valid,
|
|
// <hAcmDrv> (i) handle returned from AcmDrvLoad
|
|
// return corresponding acmdrv pointer (NULL if error)
|
|
//
|
|
static LPACMDRV AcmDrvGetPtr(HACMDRV hAcmDrv)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACMDRV lpAcmDrv;
|
|
|
|
if ((lpAcmDrv = (LPACMDRV) hAcmDrv) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (IsBadWritePtr(lpAcmDrv, sizeof(ACMDRV)))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? lpAcmDrv : NULL;
|
|
}
|
|
|
|
// AcmDrvGetHandle - verify that acmdrv pointer is valid,
|
|
// <lpAcm> (i) pointer to ACM struct
|
|
// return corresponding acmdrv handle (NULL if error)
|
|
//
|
|
static HACMDRV AcmDrvGetHandle(LPACMDRV lpAcmDrv)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HACMDRV hAcmDrv;
|
|
|
|
if ((hAcmDrv = (HACMDRV) lpAcmDrv) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? hAcmDrv : NULL;
|
|
}
|
|
|
|
// AcmStreamOpen - open acm conversion stream
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <lpwfxSrc> (i) pointer to source WAVEFORMATEX struct
|
|
// <lpwfxDst> (i) pointer to destination WAVEFORMATEX struct
|
|
// <lpwfltr> (i) pointer to WAVEFILTER struct
|
|
// <dwFlags> (i) control flags
|
|
// ACM_NONREALTIME realtime stream conversion not required
|
|
// ACM_QUERY return TRUE if conversion would be supported
|
|
// return handle (NULL if error)
|
|
//
|
|
static HACMSTREAM WINAPI AcmStreamOpen(HACM hAcm, LPWAVEFORMATEX lpwfxSrc,
|
|
LPWAVEFORMATEX lpwfxDst, LPWAVEFILTER lpwfltr, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HACMSTREAM hAcmStream = NULL;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!WavFormatIsValid(lpwfxSrc))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!WavFormatIsValid(lpwfxDst))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
DWORD dwFlagsStreamOpen = 0;
|
|
|
|
// set non-realtime flag if necessary
|
|
//
|
|
if (dwFlags & ACM_NONREALTIME)
|
|
dwFlagsStreamOpen |= ACM_STREAMOPENF_NONREALTIME;
|
|
|
|
// set query flag if necessary
|
|
//
|
|
if (dwFlags & ACM_QUERY)
|
|
dwFlagsStreamOpen |= ACM_STREAMOPENF_QUERY;
|
|
|
|
// open (or query) the acm conversion stream
|
|
//
|
|
if ((lpAcm->nLastError = acmStreamOpen(&hAcmStream,
|
|
NULL, lpwfxSrc, lpwfxDst, lpwfltr, 0, 0, dwFlagsStreamOpen)) != 0)
|
|
{
|
|
if ((dwFlags & ACM_QUERY) &&
|
|
lpAcm->nLastError == ACMERR_NOTPOSSIBLE)
|
|
{
|
|
fSuccess = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamOpen failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
}
|
|
}
|
|
|
|
// close stream if we are finished with it
|
|
//
|
|
if (!fSuccess || (dwFlags & ACM_QUERY))
|
|
{
|
|
if (AcmStreamClose(hAcm, hAcmStream) != 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (dwFlags & ACM_QUERY)
|
|
return fSuccess ? (HACMSTREAM) TRUE : (HACMSTREAM) FALSE;
|
|
else
|
|
return fSuccess ? hAcmStream : NULL;
|
|
}
|
|
|
|
// AcmStreamClose - close acm conversion stream
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hAcmStream> (i) handle returned from AcmStreamOpen
|
|
// return 0 if success
|
|
//
|
|
static int WINAPI AcmStreamClose(HACM hAcm, HACMSTREAM hAcmStream)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// close the acm conversion stream
|
|
//
|
|
else if (hAcmStream != NULL &&
|
|
(lpAcm->nLastError = acmStreamClose(hAcmStream, 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamClose failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
|
|
else if (hAcmStream = NULL, FALSE)
|
|
;
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// AcmStreamSize - calculate stream buffer size
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hAcmStream> (i) handle returned from AcmStreamOpen
|
|
// <sizBuf> (i) size of buffer in bytes
|
|
// <dwFlags> (i) control flags
|
|
// ACM_SOURCE sizBuf is source, calc destination
|
|
// ACM_DESTINATION sizBuf is destination, calc source
|
|
// return buffer size, -1 if error
|
|
//
|
|
static long WINAPI AcmStreamSize(HACM hAcm, HACMSTREAM hAcmStream, long sizBuf, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm = NULL;
|
|
DWORD sizBufRet = 0;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hAcmStream == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (sizBuf == 0)
|
|
sizBufRet = 0;
|
|
|
|
else
|
|
{
|
|
DWORD dwFlagsSize = 0;
|
|
if (dwFlags & ACM_SOURCE)
|
|
dwFlagsSize |= ACM_STREAMSIZEF_SOURCE;
|
|
if (dwFlags & ACM_DESTINATION)
|
|
dwFlagsSize |= ACM_STREAMSIZEF_DESTINATION;
|
|
|
|
if ((lpAcm->nLastError = acmStreamSize(hAcmStream,
|
|
(DWORD) sizBuf, &sizBufRet, dwFlagsSize)) != 0)
|
|
{
|
|
if (lpAcm->nLastError == ACMERR_NOTPOSSIBLE)
|
|
{
|
|
// not a fatal error; just return buffer size as zero
|
|
//
|
|
fSuccess = TraceTRUE(NULL);
|
|
sizBufRet = 0;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamSize failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
}
|
|
}
|
|
|
|
return fSuccess ? (long) sizBufRet : -1;
|
|
|
|
}
|
|
|
|
// AcmStreamConvert - convert wav data from one format to another
|
|
// <hAcm> (i) handle returned from AcmInit
|
|
// <hAcmStream> (i) handle returned from AcmStreamOpen
|
|
// <hpBufSrc> (i) buffer containing bytes to reformat
|
|
// <sizBufSrc> (i) size of buffer in bytes
|
|
// <hpBufDst> (o) buffer to contain new format
|
|
// <sizBufDst> (i) size of buffer in bytes
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return count of bytes in destination buffer (-1 if error)
|
|
//
|
|
// NOTE: the destination buffer must be large enough to hold the result
|
|
//
|
|
static long WINAPI AcmStreamConvert(HACM hAcm, HACMSTREAM hAcmStream,
|
|
void _huge *hpBufSrc, long sizBufSrc,
|
|
void _huge *hpBufDst, long sizBufDst,
|
|
DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACM lpAcm;
|
|
long cbDst;
|
|
|
|
if ((lpAcm = AcmGetPtr(hAcm)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hAcmStream == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
ACMSTREAMHEADER ash;
|
|
|
|
MemSet(&ash, 0, sizeof(ash));
|
|
|
|
// initialize stream header
|
|
//
|
|
ash.cbStruct = sizeof(ash);
|
|
ash.pbSrc = (LPBYTE) hpBufSrc;
|
|
ash.cbSrcLength = (DWORD) sizBufSrc;
|
|
ash.pbDst = (LPBYTE) hpBufDst;
|
|
ash.cbDstLength = (DWORD) sizBufDst;
|
|
|
|
// prepare stream header
|
|
//
|
|
if ((lpAcm->nLastError = acmStreamPrepareHeader(hAcmStream,
|
|
&ash, 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamPrepareHeader failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
|
|
else
|
|
{
|
|
// perform the conversion
|
|
//
|
|
if ((lpAcm->nLastError = acmStreamConvert(hAcmStream,
|
|
&ash, ACM_STREAMCONVERTF_BLOCKALIGN)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamConvert failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
else
|
|
{
|
|
// save count of bytes in destination buffer
|
|
//
|
|
cbDst = (long) ash.cbDstLengthUsed;
|
|
}
|
|
|
|
// reset these to original values before unprepare
|
|
//
|
|
ash.cbSrcLength = (DWORD) sizBufSrc;
|
|
ash.cbDstLength = (DWORD) sizBufDst;
|
|
|
|
// unprepare stream header (even if conversion failed)
|
|
//
|
|
if ((lpAcm->nLastError = acmStreamUnprepareHeader(hAcmStream,
|
|
&ash, 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmStreamUnprepareHeader failed (%u)\n"),
|
|
(unsigned) lpAcm->nLastError);
|
|
}
|
|
}
|
|
}
|
|
|
|
return fSuccess ? cbDst : -1;
|
|
}
|
|
|
|
BOOL CALLBACK AcmDriverLoadEnumCallback(HACMDRIVERID hadid,
|
|
DWORD dwInstance, DWORD fdwSupport)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPACMDRV lpAcmDrv;
|
|
ACMDRIVERDETAILS add;
|
|
|
|
MemSet(&add, 0, sizeof(add));
|
|
add.cbStruct = sizeof(ACMDRIVERDETAILS);
|
|
|
|
if (hadid == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpAcmDrv = (LPACMDRV)(DWORD_PTR)dwInstance) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get information about this driver
|
|
//
|
|
else if ((lpAcmDrv->nLastError = acmDriverDetails(hadid, &add, 0)) != 0)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
TracePrintf_1(NULL, 5,
|
|
TEXT("acmDriverDetails failed (%u)\n"),
|
|
(unsigned) lpAcmDrv->nLastError);
|
|
}
|
|
|
|
// check for match on manufacturer id and product id
|
|
//
|
|
else if (add.wMid == lpAcmDrv->wMid && add.wPid == lpAcmDrv->wPid)
|
|
{
|
|
lpAcmDrv->hadid = hadid; // pass driver id handle back to caller
|
|
return FALSE; // we are finished enumerating
|
|
}
|
|
|
|
return TRUE; // continue enumeration
|
|
}
|