📄 acm.c
字号:
)
{
UINT uFormatTag;
//
//
//
//
//
switch (ACM_FORMATTAGDETAILSF_QUERYMASK & fdwDetails)
{
case ACM_FORMATTAGDETAILSF_INDEX:
//
// if the index is too large, then they are asking for a
// non-existant format. return error.
//
if (ACM_DRIVER_MAX_FORMAT_TAGS <= padft->dwFormatTagIndex)
return (ACMERR_NOTPOSSIBLE);
uFormatTag = gauFormatTagIndexToTag[(UINT)padft->dwFormatTagIndex];
break;
case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
switch (padft->dwFormatTag)
{
case WAVE_FORMAT_UNKNOWN:
case WAVE_FORMAT_PCM:
uFormatTag = WAVE_FORMAT_PCM;
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
break;
case ACM_FORMATTAGDETAILSF_FORMATTAG:
if (WAVE_FORMAT_PCM != padft->dwFormatTag)
return (ACMERR_NOTPOSSIBLE);
uFormatTag = WAVE_FORMAT_PCM;
break;
//
// if this ACM driver does not understand a query type, then
// return 'not supported'
//
default:
return (MMSYSERR_NOTSUPPORTED);
}
//
//
//
//
switch (uFormatTag)
{
case WAVE_FORMAT_PCM:
padft->dwFormatTagIndex = 0;
padft->dwFormatTag = WAVE_FORMAT_PCM;
padft->cbFormatSize = sizeof(PCMWAVEFORMAT);
padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_FILTER;
padft->cStandardFormats = ACM_DRIVER_MAX_STANDARD_FORMATS_PCM;
//
// the ACM is responsible for the PCM format tag name
//
padft->szFormatTag[0] = '\0';
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
//
// return only the requested info
//
// the ACM will guarantee that the ACMFORMATTAGDETAILS structure
// passed is at least large enough to hold the base information of
// the details structure
//
padft->cbStruct = min(padft->cbStruct, sizeof(*padft));
//
//
//
return (MMSYSERR_NOERROR);
} // acmdFormatTagDetails()
//--------------------------------------------------------------------------;
//
// LRESULT acmdFormatDetails
//
// Description:
// This function handles the ACMDM_FORMAT_DETAILS message. This
// message is normally sent in response to an acmFormatDetails or
// acmFormatEnum function call. The purpose of this function is
// to get details about a specific format for a specified format tag
// supported by this ACM driver.
//
// Note that an ACM driver can return a zero length string for the
// format name if it wishes to have the ACM create a format string
// for it. This is strongly recommended to simplify internationalizing
// the driver--the ACM will automatically take care of that. The
// following formula is used to format a string by the ACM:
//
// <nSamplesPerSec> kHz, <bit depth> bit, [Mono | Stereo | nChannels]
//
// <bit depth> = <nAvgBytesPerSec> * 8 / nSamplesPerSec / nChannels;
//
// Arguments:
// PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
// This structure is [optionally] allocated during the DRV_OPEN message
// which is handled by the acmdDriverOpen function.
//
// LPACMFORMATDETAILS padf: Pointer to an ACMFORMATDETAILS structure
// that describes what format (for a specified format tag) to retrieve
// details for.
//
// DWORD fdwDetails: Flags defining what format for a specified format
// tag to retrieve the details for.
//
// Return (LRESULT):
// The return value is zero (MMSYSERR_NOERROR) if this function
// succeeds with no errors. The return value is a non-zero error code
// if the function fails.
//
// The driver should return MMSYSERR_NOTSUPPORTED if the query type
// specified in fdwDetails is not supported. An ACM driver must
// support at least the following query types:
//
// ACM_FORMATDETAILSF_INDEX: Indicates that a format index for the
// format tag was given in the dwFormatIndex member of the
// ACMFORMATDETAILS structure. The format details must be returned in
// the structure specified by padf. The index ranges from zero to one
// less than the cStandardFormats member returned in the
// ACMFORMATTAGDETAILS structure for a format tag.
//
// ACM_FORMATDETAILSF_FORMAT: Indicates that a WAVEFORMATEX structure
// pointed to by pwfx of the ACMFORMATDETAILS structure was given and
// the remaining details should be returned. The dwFormatTag member
// of the ACMFORMATDETAILS will be initialized to the same format
// tag as the pwfx member specifies. This query type may be used to
// get a string description of an arbitrary format structure.
//
// If the details for the specified format cannot be retrieved
// from this driver, then ACMERR_NOTPOSSIBLE should be returned.
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdFormatDetails
(
PDRIVERINSTANCE pdi,
LPACMFORMATDETAILS padf,
DWORD fdwDetails
)
{
LPWAVEFORMATEX pwfx;
UINT uFormatIndex;
UINT u;
//
//
//
//
//
switch (ACM_FORMATDETAILSF_QUERYMASK & fdwDetails)
{
//
// enumerate by index
//
// verify that the format tag is something we know about and
// return the details on the 'standard format' supported by
// this driver at the specified index...
//
case ACM_FORMATDETAILSF_INDEX:
//
// verify that the format tag is something we know about
//
if (WAVE_FORMAT_PCM != padf->dwFormatTag)
return (ACMERR_NOTPOSSIBLE);
if (ACM_DRIVER_MAX_STANDARD_FORMATS_PCM <= padf->dwFormatIndex)
return (ACMERR_NOTPOSSIBLE);
//
// put some stuff in more accessible variables--note that we
// bring variable sizes down to a reasonable size for 16 bit
// code...
//
pwfx = padf->pwfx;
uFormatIndex = (UINT)padf->dwFormatIndex;
//
// now fill in the format structure
//
pwfx->wFormatTag = WAVE_FORMAT_PCM;
u = uFormatIndex / (ACM_DRIVER_MAX_BITSPERSAMPLE_PCM * ACM_DRIVER_MAX_CHANNELS);
pwfx->nSamplesPerSec = gauFormatIndexToSampleRate[u];
u = uFormatIndex % ACM_DRIVER_MAX_CHANNELS;
pwfx->nChannels = u + 1;
u = (uFormatIndex / ACM_DRIVER_MAX_CHANNELS) % ACM_DRIVER_MAX_CHANNELS;
pwfx->wBitsPerSample = (WORD)gauFormatIndexToBitsPerSample[u];
pwfx->nBlockAlign = PCM_BLOCKALIGNMENT(pwfx);
pwfx->nAvgBytesPerSec = PCM_AVGBYTESPERSEC(pwfx);
//
// note that the cbSize field is NOT valid for PCM formats
//
// pwfx->cbSize = 0;
break;
//
// return details on specified format
//
// the caller normally uses this to verify that the format is
// supported and to retrieve a string description...
//
case ACM_FORMATDETAILSF_FORMAT:
if (!pcmIsValidFormat(padf->pwfx))
return (ACMERR_NOTPOSSIBLE);
break;
default:
//
// don't know how to do the query type passed--return 'not
// supported'.
//
return (MMSYSERR_NOTSUPPORTED);
}
//
// return the size of the valid information we are returning
//
// the ACM will guarantee that the ACMFORMATDETAILS structure
// passed is at least large enough to hold the base structure
//
// note that we let the ACM create the format string for us since
// we require no special formatting (and don't want to deal with
// internationalization issues, etc). simply set the string to
// a zero length.
//
padf->cbStruct = min(padf->cbStruct, sizeof(*padf));
padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_FILTER;
padf->szFormat[0] = '\0';
//
//
//
return (MMSYSERR_NOERROR);
} // acmdFormatDetails()
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// LRESULT acmdFilterTagDetails
//
// Description:
//
//
// Arguments:
// PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
// This structure is [optionally] allocated during the DRV_OPEN message
// which is handled by the acmdDriverOpen function.
//
// LPACMFILTERTAGDETAILS padft:
//
// DWORD fdwDetails:
//
// Return (LRESULT):
//
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdFilterTagDetails
(
PDRIVERINSTANCE pdi,
LPACMFILTERTAGDETAILS padft,
DWORD fdwDetails
)
{
UINT uIds;
UINT uFilterTag;
//
//
//
//
//
switch (ACM_FILTERTAGDETAILSF_QUERYMASK & fdwDetails)
{
case ACM_FILTERTAGDETAILSF_INDEX:
//
// if the index is too large, then they are asking for a
// non-existant filter. return error.
//
if (ACM_DRIVER_MAX_FILTER_TAGS <= padft->dwFilterTagIndex)
return (ACMERR_NOTPOSSIBLE);
uFilterTag = (UINT)gadwFilterTagIndexToTag[(UINT)padft->dwFilterTagIndex];
break;
case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
switch (padft->dwFilterTag)
{
case WAVE_FILTER_UNKNOWN:
case WAVE_FILTER_ECHO:
uFilterTag = WAVE_FILTER_ECHO;
break;
case WAVE_FILTER_VOLUME:
uFilterTag = WAVE_FILTER_VOLUME;
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
break;
case ACM_FILTERTAGDETAILSF_FILTERTAG:
switch (padft->dwFilterTag)
{
case WAVE_FILTER_VOLUME:
uFilterTag = WAVE_FILTER_VOLUME;
break;
case WAVE_FILTER_ECHO:
uFilterTag = WAVE_FILTER_ECHO;
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
break;
//
// if this driver does not understand a query type, then
// return 'not supported'
//
default:
return (MMSYSERR_NOTSUPPORTED);
}
//
//
//
//
switch (uFilterTag)
{
case WAVE_FILTER_VOLUME:
padft->dwFilterTagIndex = 0;
padft->dwFilterTag = WAVE_FILTER_VOLUME;
padft->cbFilterSize = sizeof(VOLUMEWAVEFILTER);
padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_FILTER;
padft->cStandardFilters = ACM_DRIVER_MAX_VOLUME_FILTERS;
uIds = IDS_ACM_DRIVER_TAG_NAME_VOLUME;
break;
case WAVE_FILTER_ECHO:
padft->dwFilterTagIndex = 1;
padft->dwFilterTag = WAVE_FILTER_ECHO;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -