📄 codec.c
字号:
}
break;
case ACM_FORMATTAGDETAILSF_FORMATTAG:
switch (padft->dwFormatTag)
{
case WAVE_FORMAT_GSM610:
uFormatTag = WAVE_FORMAT_GSM610;
break;
case WAVE_FORMAT_PCM:
uFormatTag = WAVE_FORMAT_PCM;
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
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_CODEC;
padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_PCM;
//
// the ACM is responsible for the PCM format tag name
//
padft->szFormatTag[0] = '\0';
break;
case WAVE_FORMAT_GSM610:
padft->dwFormatTagIndex = 1;
padft->dwFormatTag = WAVE_FORMAT_GSM610;
padft->cbFormatSize = sizeof(GSM610WAVEFORMAT);
padft->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
padft->cStandardFormats = ACM_DRIVER_MAX_FORMATS_GSM610;
LoadStringCodec(pdi->hinst,
IDS_ACM_DRIVER_TAG_NAME,
padft->szFormatTag,
SIZEOFACMSTR(padft->szFormatTag));
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 uq; // quotient and
UINT ur; // remainder for arithmetic below.
//
//
//
//
//
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:
//
// 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;
switch (padf->dwFormatTag)
{
case WAVE_FORMAT_PCM:
if (ACM_DRIVER_MAX_FORMATS_PCM <= padf->dwFormatIndex)
return (ACMERR_NOTPOSSIBLE);
//
// now fill in the format structure
//
pwfx->wFormatTag = WAVE_FORMAT_PCM;
uq = (UINT) padf->dwFormatIndex;
ur = uq % ACM_DRIVER_MAX_CHANNELS;
uq = uq / ACM_DRIVER_MAX_CHANNELS;
pwfx->nChannels = ur + 1;
ur = uq % ACM_DRIVER_MAX_BITSPERSAMPLE_PCM;
uq = uq / ACM_DRIVER_MAX_BITSPERSAMPLE_PCM;
pwfx->wBitsPerSample = (WORD)gauPcmFormatIndexToBitsPerSample[ur];
ur = uq % ACM_DRIVER_MAX_SAMPLE_RATES;
uq = uq / ACM_DRIVER_MAX_SAMPLE_RATES;
pwfx->nSamplesPerSec = gauFormatIndexToSampleRate[ur];
pwfx->nBlockAlign = PCM_BLOCKALIGNMENT((LPPCMWAVEFORMAT)pwfx);
pwfx->nAvgBytesPerSec = PCM_AVGBYTESPERSEC((LPPCMWAVEFORMAT)pwfx);
//
// note that the cbSize field is NOT valid for PCM
// formats
//
// pwfx->cbSize = 0;
break;
case WAVE_FORMAT_GSM610:
if (ACM_DRIVER_MAX_FORMATS_GSM610 <= padf->dwFormatIndex)
return (ACMERR_NOTPOSSIBLE);
pwfx->wFormatTag = LOWORD(padf->dwFormatTag);
uq = (UINT) padf->dwFormatIndex;
ur = uq % ACM_DRIVER_MAX_CHANNELS;
uq = uq / ACM_DRIVER_MAX_CHANNELS;
pwfx->nChannels = ur + 1;
ur = uq % ACM_DRIVER_MAX_SAMPLE_RATES;
uq = uq / ACM_DRIVER_MAX_SAMPLE_RATES;
pwfx->nSamplesPerSec = gauFormatIndexToSampleRate[ur];
pwfx->wBitsPerSample = GSM610_BITS_PER_SAMPLE;
pwfx->nBlockAlign = GSM610_BLOCKALIGNMENT(pwfx);
pwfx->nAvgBytesPerSec = GSM610_AVGBYTESPERSEC(pwfx);
//
//
//
pwfx->cbSize = GSM610_WFX_EXTRA_BYTES;
((LPGSM610WAVEFORMAT)pwfx)->wSamplesPerBlock
= GSM610_SAMPLESPERBLOCK(pwfx);
//
// acm format details support flags.
//
padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
break;
default:
return (ACMERR_NOTPOSSIBLE);
}
//
// 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:
pwfx = padf->pwfx;
switch (pwfx->wFormatTag)
{
case WAVE_FORMAT_PCM:
if (!pcmIsValidFormat(pwfx))
return (ACMERR_NOTPOSSIBLE);
break;
case WAVE_FORMAT_GSM610:
if (!gsm610IsValidFormat(pwfx))
return (ACMERR_NOTPOSSIBLE);
break;
default:
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.
//
//
// acm format details support flags. if 8-bit pcm is
// completely disabled (both realtime and non-realtime)
// then don't set SUPPORTF_CODEC.
//
padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
padf->cbStruct = min(padf->cbStruct, sizeof(*padf));
padf->szFormat[0] = '\0';
//
//
//
return (MMSYSERR_NOERROR);
} // acmdFormatDetails()
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// LRESULT acmdStreamOpen
//
// Description:
// This function handles the ACMDM_STREAM_OPEN message. This message
// is sent to initiate a new conversion stream. This is usually caused
// by an application calling acmStreamOpen. If this function is
// successful, then one or more ACMDM_STREAM_CONVERT messages will be
// sent to convert individual buffers (user calls acmStreamConvert).
//
// Note that an ACM driver will not receive open requests for ASYNC
// or FILTER operations unless the ACMDRIVERDETAILS_SUPPORTF_ASYNC
// or ACMDRIVERDETAILS_SUPPORTF_FILTER flags are set in the
// ACMDRIVERDETAILS structure. There is no need for the driver to
// check for these requests unless it sets those support bits.
//
// If the ACM_STREAMOPENF_QUERY flag is set in the padsi->fdwOpen
// member, then no resources should be allocated. Just verify that
// the conversion request is possible by this driver and return the
// appropriate error (either ACMERR_NOTPOSSIBLE or MMSYSERR_NOERROR).
// The driver will NOT receive an ACMDM_STREAM_CLOSE for queries.
//
// If the ACM_STREAMOPENF_NONREALTIME bit is NOT set, then conversion
// must be done in 'real-time'. This is a tough one to describe
// exactly. If the driver may have trouble doing the conversion without
// breaking up the audio, then a configuration dialog might be used
// to allow the user to specify whether the real-time conversion
// request should be succeeded. DO NOT SUCCEED THE CALL UNLESS YOU
// ACTUALLY CAN DO REAL-TIME CONVERSIONS! There may be another driver
// installed that can--so if you succeed the call you are hindering
// the performance of the user's system!
//
// 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -