📄 acm.c
字号:
// driver supports conversions on the same format tag. as an example,
// the PCM converter that is built into the ACM sets this bit (and only
// this bit) because it converts only between PCM formats (bits, sample
// rate).
//
// ACMDRIVERDETAILS_SUPPORTF_FILTER: this flag is set if the driver
// supports transformations on a single format tag but does change
// the base characteristics of the format (bit depth, sample rate, etc
// will remain the same). for example, a driver that changed the
// 'volume' of PCM data or applied a low pass filter would set this bit.
//
add.fdwSupport = ACMDRIVERDETAILS_SUPPORTF_ACM;
//
// the number of individual format tags this ACM driver supports. for
// example, if a driver uses the WAVE_FORMAT_IMA_ADPCM and
// WAVE_FORMAT_PCM format tags, then this value would be two. if the
// driver only supports filtering on WAVE_FORMAT_PCM, then this value
// would be one. if this driver supported WAVE_FORMAT_ALAW,
// WAVE_FORMAT_MULAW and WAVE_FORMAT_PCM, then this value would be
// three. etc, etc.
//
add.cFormatTags = ACM_DRIVER_MAX_FORMAT_TAGS;
//
// the number of individual filter tags this ACM driver supports. if
// a driver supports no filters (ACMDRIVERDETAILS_SUPPORTF_FILTER is
// NOT set in the fdwSupport member), then this value must be zero.
//
add.cFilterTags = ACM_DRIVER_MAX_FILTER_TAGS;
//
// the remaining members in the ACMDRIVERDETAILS structure are sometimes
// not needed. because of this we make a quick check to see if we
// should go through the effort of filling in these members.
//
if (FIELD_OFFSET(ACMDRIVERDETAILS, hicon) < cbStruct)
{
//
// fill in the hicon member will a handle to a custom icon for
// the ACM driver. this allows the driver to be represented by
// an application graphically (usually this will be a company
// logo or something). if a driver does not wish to have a custom
// icon displayed, then simply set this member to NULL and a
// generic icon will be displayed instead.
//
// See the MSFILTER sample for a ACM which contains a custom icon.
//
add.hicon = NULL;
//
// the short name and long name are used to represent the driver
// in a unique description. the short name is intended for small
// display areas (for example, in a menu or combo box). the long
// name is intended for more descriptive displays (for example,
// in an 'about box').
//
// NOTE! an ACM driver should never place formatting characters
// of any sort in these strings (for example CR/LF's, etc). it
// is up to the application to format the text.
//
LoadStringACM(pdi->hinst, IDS_ACM_DRIVER_SHORTNAME, add.szShortName, SIZEOFACMSTR(add.szShortName));
LoadStringACM(pdi->hinst, IDS_ACM_DRIVER_LONGNAME, add.szLongName, SIZEOFACMSTR(add.szLongName));
//
// the last three members are intended for 'about box' information.
// these members are optional and may be zero length strings if
// the driver wishes.
//
// NOTE! an ACM driver should never place formatting characters
// of any sort in these strings (for example CR/LF's, etc). it
// is up to the application to format the text.
//
if (FIELD_OFFSET(ACMDRIVERDETAILS, szCopyright) < cbStruct)
{
LoadStringACM(pdi->hinst, IDS_ACM_DRIVER_COPYRIGHT, add.szCopyright, SIZEOFACMSTR(add.szCopyright));
LoadStringACM(pdi->hinst, IDS_ACM_DRIVER_LICENSING, add.szLicensing, SIZEOFACMSTR(add.szLicensing));
LoadStringACM(pdi->hinst, IDS_ACM_DRIVER_FEATURES, add.szFeatures, SIZEOFACMSTR(add.szFeatures));
}
}
//
// now copy the correct number of bytes to the caller's buffer
//
_fmemcpy(padd, &add, (UINT)add.cbStruct);
//
// success!
//
return (MMSYSERR_NOERROR);
} // acmdDriverDetails()
//--------------------------------------------------------------------------;
//
// LRESULT acmdDriverAbout
//
// Description:
// This function is called to handle the ACMDM_DRIVER_ABOUT message.
// An ACM driver has the option of displaying its own 'about box' or
// letting the ACM (or calling application) display one for it. This
// message is normally sent by the Control Panel's Sound Mapper
// option.
//
// It is recommended that an ACM driver allow a default about box
// be displayed for it--there should be no reason to bloat the size
// of a driver to simply display copyright, etc information when that
// information is contained in the ACMDRIVERDETAILS structure.
//
// 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.
//
// HWND hwnd: Handle to parent window to use when displaying the
// Configururation dialog box. An ACM driver is _required_ to display a
// modal dialog box using this hwnd argument as the parent. This
// argument may be (HWND)-1 which tells the driver that it is only
// being queried for about box support.
//
// Return (LRESULT):
// The return value is MMSYSERR_NOTSUPPORTED if the ACM driver does
// not support a custom dialog box. In this case, the ACM or calling
// application will display a generic about box using the information
// contained in the ACMDRIVERDETAILS structure returned by the
// ACMDM_DRIVER_DETAILS message.
//
// If the driver chooses to display its own dialog box, then after
// the dialog is dismissed by the user, MMSYSERR_NOERROR should be
// returned.
//
// If the hwnd argument is equal to (HWND)-1, then no dialog should
// be displayed (the driver is only being queried for support). The
// driver must still return MMSYSERR_NOERROR (supported) or
// MMSYSERR_NOTSUPPORTED (no custom about box supported).
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdDriverAbout
(
PDRIVERINSTANCE pdi,
HWND hwnd
)
{
//
// first check to see if we are only being queried for custom about
// box support. if hwnd == (HWND)-1 then we are being queried and
// should return MMSYSERR_NOTSUPPORTED for 'not supported' and
// MMSYSERR_NOERROR for 'supported'.
//
if ((HWND)-1 == hwnd)
{
//
// this ACM driver does NOT support a custom about box, so
// return MMSYSERR_NOTSUPPORTED...
//
return (MMSYSERR_NOTSUPPORTED);
}
//
// this driver does not support a custom dialog, so tell the ACM or
// calling application to display one for us. note that this is the
// _recommended_ method for consistency and simplicity of ACM drivers.
// why write code when you don't have to?
//
return (MMSYSERR_NOTSUPPORTED);
} // acmdDriverAbout()
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// LRESULT acmdFormatSuggest
//
// Description:
// This function handles the ACMDM_FORMAT_SUGGEST message. The purpose
// of this function is to provide a way for the ACM, a wave mapper or
// an application to quickly get a destination format that this driver
// can convert the source format to. The 'suggested' format should
// be as close to a common format as possible. This message is normally
// sent in response to an acmFormatSuggest function call.
//
// Another way to think about this message is: what format would this
// driver like to convert the source format to?
//
// The caller may place restrictions on the destination format that
// should be suggested. The padfs->fdwSuggest member contains the
// restriction bits passed by the caller--see the description for
// the return value for more information.
//
// 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.
//
// LPACMDRVFORMATSUGGEST padfs: Pointer to an ACMDRVFORMATSUGGEST
// structure that describes the source and destination (possibly with
// restrictions) for a conversion.
//
// 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 one or more of
// the destination restriction bits is not supported. It is strongly
// recommended that the driver support at least the following suggestion
// restriction bits:
//
// ACM_FORMATSUGGESTF_WFORMATTAG: The destination format tag must be
// the same as the wFormatTag member in the destination format header.
//
// ACM_FORMATSUGGESTF_NCHANNELS: The destination channel count must be
// the same as the nChannels member in the destination format header.
//
// ACM_FORMATSUGGESTF_NSAMPLESPERSEC: The destination samples per
// second must be the same as the nSamplesPerSec member in the
// destination format header.
//
// ACM_FORMATSUGGESTF_WBITSPERSAMPLE: The destination bits per sample
// must be the same as the wBitsPerSample member in the destination
// format header.
//
// If no destintation format can be suggested, then the driver should
// return ACMERR_NOTPOSSIBLE.
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdFormatSuggest
(
PDRIVERINSTANCE pdi,
LPACMDRVFORMATSUGGEST padfs
)
{
#define ACMD_FORMAT_SUGGEST_SUPPORT (ACM_FORMATSUGGESTF_WFORMATTAG | \
ACM_FORMATSUGGESTF_NCHANNELS | \
ACM_FORMATSUGGESTF_NSAMPLESPERSEC |\
ACM_FORMATSUGGESTF_WBITSPERSAMPLE)
LPWAVEFORMATEX pwfxSrc;
LPWAVEFORMATEX pwfxDst;
LPIMAALGORITHWAVEFORMAT pwfadpcm;
DWORD fdwSuggest;
//
// grab the suggestion restriction bits and verify that we support
// the ones that are specified... an ACM driver must return the
// MMSYSERR_NOTSUPPORTED if the suggestion restriction bits specified
// are not supported.
//
fdwSuggest = (ACM_FORMATSUGGESTF_TYPEMASK & padfs->fdwSuggest);
if (~ACMD_FORMAT_SUGGEST_SUPPORT & fdwSuggest)
return (MMSYSERR_NOTSUPPORTED);
//
// get the source and destination formats in more convenient variables
//
pwfxSrc = padfs->pwfxSrc;
pwfxDst = padfs->pwfxDst;
//
//
//
//
switch (pwfxSrc->wFormatTag)
{
case WAVE_FORMAT_PCM:
//
// strictly verify that the source format is acceptable for
// this driver
//
if (!pcmIsValidFormat(pwfxSrc))
break;
//
// if the destination format tag is restricted, verify that
// it is within our capabilities...
//
// this driver is only able to encode to IMA ADPCM
//
if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
{
if (WAVE_FORMAT_IMA_ADPCM != pwfxDst->wFormatTag)
return (ACMERR_NOTPOSSIBLE);
}
else
{
pwfxDst->wFormatTag = WAVE_FORMAT_IMA_ADPCM;
}
//
// if the destination channel count is restricted, verify that
// it is within our capabilities...
//
// this driver is not able to change the number of channels
//
if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
{
if (pwfxSrc->nChannels != pwfxDst->nChannels)
return (ACMERR_NOTPOSSIBLE);
}
else
{
pwfxDst->nChannels = pwfxSrc->nChannels;
}
//
// if the destination samples per second is restricted, verify
// that it is within our capabilities...
//
// this driver is not able to change the sample rate
//
if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
{
if (pwfxSrc->nSamplesPerSec != pwfxDst->nSamplesPerSec)
return (ACMERR_NOTPOSSIBLE);
}
else
{
pwfxDst->nSamplesPerSec = pwfxSrc->nSamplesPerSec;
}
//
// if the destination bits per sample is restricted, verify
// that it is within our capabilities...
//
// this driver is only able to encode to 4 bit
//
if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
{
if (IMAALGORITH_BITS_PER_SAMPLE != pwfxDst->wBitsPerSample)
return (ACMERR_NOTPOSSIBLE);
}
else
{
pwfxDst->wBitsPerSample = IMAALGORITH_BITS_PER_SAMPLE;
}
//
// at this point, we have filled in all fields except the
// following for our 'suggested' destination format:
//
// nAvgBytesPerSec
// nBlockAlign
// cbSize
//
// wSamplesPerBlock -> IMA ADPCM extended information
//
pwfxDst->nBlockAlign = IMAAlgorithBlockAlign(pwfxDst);
pwfxDst->nAvgBytesPerSec = IMAAlgorithAvgBytesPerSec(pwfxDst);
pwfxDst->cbSize = IMAALGORITH_WFX_EXTRA_BYTES;
pwfadpcm = (LPIMAALGORITHWAVEFORMAT)pwfxDst;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -