📄 acm.c
字号:
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992-1999 G&G Lab Corporation
//
//--------------------------------------------------------------------------;
//
// ACM.c
//
// Description:
// This file contains the DriverProc and other routines which respond
// to ACM messages.
//
//
//==========================================================================;
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <mmddk.h>
#include <ctype.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include "ACM.h"
#include "IMAAlgorith.h"
#include "debug.h"
const UINT gauFormatTagIndexToTag[] =
{
WAVE_FORMAT_PCM,
WAVE_FORMAT_IMA_ADPCM
};
#define ACM_DRIVER_MAX_FORMAT_TAGS SIZEOF_ARRAY(gauFormatTagIndexToTag)
#define ACM_DRIVER_MAX_FILTER_TAGS 0
//
// array of sample rates supported
//
//
const UINT gauFormatIndexToSampleRate[] =
{
8000,
11025,
22050,
44100
};
#ifdef IMAALGORITH_USECONFIGUR
//
// Required by Configur.c as well as ACM.c.
//
const UINT ACM_DRIVER_MAX_SAMPLE_RATES = SIZEOF_ARRAY(gauFormatIndexToSampleRate);
const UINT ACM_DRIVER_MAX_CHANNELS = IMAALGORITH_MAX_CHANNELS;
#else
#define ACM_DRIVER_MAX_SAMPLE_RATES SIZEOF_ARRAY(gauFormatIndexToSampleRate)
#define ACM_DRIVER_MAX_CHANNELS IMAALGORITH_MAX_CHANNELS
#endif
//
// array of bits per sample supported
//
//
const UINT gauFormatIndexToBitsPerSample[] =
{
8,
16
};
#define ACM_DRIVER_MAX_BITSPERSAMPLE_PCM SIZEOF_ARRAY(gauFormatIndexToBitsPerSample)
#define ACM_DRIVER_MAX_BITSPERSAMPLE_ADPCM 1
//
// number of formats we enumerate per channel is number of sample rates
// times number of channels times number of types (bits per sample).
//
#define ACM_DRIVER_MAX_FORMATS_PCM (ACM_DRIVER_MAX_SAMPLE_RATES * \
ACM_DRIVER_MAX_CHANNELS * \
ACM_DRIVER_MAX_BITSPERSAMPLE_PCM)
#define ACM_DRIVER_MAX_FORMATS_ADPCM (ACM_DRIVER_MAX_SAMPLE_RATES * \
ACM_DRIVER_MAX_CHANNELS * \
ACM_DRIVER_MAX_BITSPERSAMPLE_ADPCM)
#ifdef IMAALGORITH_USECONFIGUR
//
// This array describes the Configururation settings for this ACM.
//
// Each line in the realtime encode/decode rate listbox must have one of
// these structures to describe it. The type of line is defined in
// nFormatType, which can have one of the following values:
//
// CONFIGUR_RLF_NONUMBER - the string in idsFormat is displayed as is.
// CONFIGUR_RLF_MONOONLY - dwMonoRate is written into idsFormat, then
// displayed as a mono rate.
// CONFIGUR_RLF_STEREOONLY - dwMonoRate is written into idsFormat, then
// displayed as a stereo rate.
// CONFIGUR_RLF_MONOSTEREO - dwMonoRate followed by nRate/2 are written
// into idsFormat, then displayed as a pair
// of mono and stereo rates.
//
// The index to the gaRateListFormat array corresponds to the value which
// is stored as Configururation information in the registry or .ini file.
// To find out if a certain conversion can be performed in real time,
// check that:
//
// SamplingRate <= gaRateListFormat[ConfigurSetting].dwMonoRate / nChannels
//
// Note: The gaRateListFormat array must change when
// gauFormatIndexToSampleRate changes.
//
const RATELISTFORMAT gaRateListFormat[] =
{
{ CONFIGUR_RLF_NONUMBER, IDS_CONFIGUR_NORATES, 0 },
{ CONFIGUR_RLF_MONOONLY, IDS_CONFIGUR_MONOONLY, 8000 }, // gauFormatIndexToSampleRate[0]
{ CONFIGUR_RLF_MONOONLY, IDS_CONFIGUR_MONOONLY, 11025 }, // gauFormatIndexToSampleRate[1]
{ CONFIGUR_RLF_STEREOONLY, IDS_CONFIGUR_STEREOONLY, 16000 }, // 2 * gauFormatIndexToSampleRate[0]
{ CONFIGUR_RLF_MONOSTEREO, IDS_CONFIGUR_MONOSTEREO, 22050 }, // gauFormatIndexToSampleRate[2]
{ CONFIGUR_RLF_MONOSTEREO, IDS_CONFIGUR_MONOSTEREO, 44100 }, // gauFormatIndexToSampleRate[3]
{ CONFIGUR_RLF_NONUMBER, IDS_CONFIGUR_ALLRATES, 88200 } // 2 * gauFormatIndexToSampleRate[3]
};
const UINT IMAALGORITH_CONFIGUR_NUMSETTINGS = SIZEOF_ARRAY( gaRateListFormat );
#endif // IMAALGORITH_USECONFIGUR
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// int LoadStringACM
//
// Description:
// This function should be used by all ACMs to load resource strings
// which will be passed back to the ACM. It works correctly for all
// platforms, as follows:
//
// Win16: Compiled to LoadString to load ANSI strings.
//
// Win32: The 32-bit ACM always expects Unicode strings. Therefore,
// when UNICODE is defined, this function is compiled to
// LoadStringW to load a Unicode string. When UNICODE is
// not defined, this function loads an ANSI string, converts
// it to Unicode, and returns the Unicode string to the
// ACM.
//
// Note that you may use LoadString for other strings (strings which
// will not be passed back to the ACM), because these strings will
// always be consistent with the definition of UNICODE.
//
// Arguments:
// Same as LoadString, except that it expects an LPSTR for Win16 and a
// LPWSTR for Win32.
//
// Return (int):
// Same as LoadString.
//
//--------------------------------------------------------------------------;
#ifndef WIN32
#define LoadStringACM LoadString
#else
#ifdef UNICODE
#define LoadStringACM LoadStringW
#else
int FNGLOBAL LoadStringACM
(
HINSTANCE hinst,
UINT uID,
LPWSTR lpwstr,
int cch)
{
LPSTR lpstr;
int iReturn;
lpstr = (LPSTR)GlobalAlloc(GPTR, cch);
if (NULL == lpstr)
{
return 0;
}
iReturn = LoadStringA(hinst, uID, lpstr, cch);
if (0 == iReturn)
{
if (0 != cch)
{
lpwstr[0] = '\0';
}
}
else
{
MultiByteToWideChar( GetACP(), 0, lpstr, cch, lpwstr, cch );
}
GlobalFree((HGLOBAL)lpstr);
return iReturn;
}
#endif // UNICODE
#endif // WIN32
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// BOOL pcmIsValidFormat
//
// Description:
// This function verifies that a wave format header is a valid PCM
// header that _this_ ACM driver can deal with.
//
// Arguments:
// LPWAVEFORMATEX pwfx: Pointer to format header to verify.
//
// Return (BOOL):
// The return value is non-zero if the format header looks valid. A
// zero return means the header is not valid.
//
//--------------------------------------------------------------------------;
BOOL FNLOCAL pcmIsValidFormat
(
LPWAVEFORMATEX pwfx
)
{
if (NULL == pwfx)
return (FALSE);
if (WAVE_FORMAT_PCM != pwfx->wFormatTag)
return (FALSE);
//
// verify nChannels member is within the allowed range
//
if ((pwfx->nChannels < 1) || (pwfx->nChannels > ACM_DRIVER_MAX_CHANNELS))
return (FALSE);
//
// only allow the bits per sample that we can encode and decode with
//
if ((16 != pwfx->wBitsPerSample) && (8 != pwfx->wBitsPerSample))
return (FALSE);
//
// now verify that the block alignment is correct..
//
if (PCM_BLOCKALIGNMENT(pwfx) != pwfx->nBlockAlign)
return (FALSE);
//
// finally, verify that avg bytes per second is correct
//
if (PCM_AVGBYTESPERSEC(pwfx) != pwfx->nAvgBytesPerSec)
return (FALSE);
return (TRUE);
} // pcmIsValidFormat()
//--------------------------------------------------------------------------;
//
// BOOL IMAAlgorithIsValidFormat
//
// Description:
// This function verifies that a wave format header is a valid
// IMA ADPCM header that _this_ ACM driver can deal with.
//
// Arguments:
// LPWAVEFORMATEX pwfx: Pointer to format header to verify.
//
// Return (BOOL):
// The return value is non-zero if the format header looks valid. A
// zero return means the header is not valid.
//
//--------------------------------------------------------------------------;
BOOL FNLOCAL IMAAlgorithIsValidFormat
(
LPWAVEFORMATEX pwfx
)
{
LPIMAALGORITHWAVEFORMAT pwfadpcm;
if (NULL == pwfx)
return (FALSE);
if (WAVE_FORMAT_IMA_ADPCM != pwfx->wFormatTag)
return (FALSE);
//
// check wBitsPerSample
//
if (IMAALGORITH_BITS_PER_SAMPLE != pwfx->wBitsPerSample)
return (FALSE);
//
// check channels
//
if ((pwfx->nChannels < 1) || (pwfx->nChannels > IMAALGORITH_MAX_CHANNELS))
return (FALSE);
//
// Check block alignment - must be an integral number of DWORDs for
// mono, or an even number of DWORDs for stereo.
//
if( 0 != pwfx->nBlockAlign % (sizeof(DWORD)*pwfx->nChannels) )
return FALSE;
//
// cbSize must be 2 for IMA's ADPCM
//
if (IMAALGORITH_WFX_EXTRA_BYTES != pwfx->cbSize)
return (FALSE);
//
// wSamplesPerBlock must be equal to 4n+1, where n is at least 1.
//
pwfadpcm = (LPIMAALGORITHWAVEFORMAT)pwfx;
if( ( pwfadpcm->wSamplesPerBlock < 5 ) ||
( pwfadpcm->wSamplesPerBlock%4 != 1 ) )
return FALSE;
return (TRUE);
} // IMAAlgorithIsValidFormat()
//==========================================================================;
//
//
//
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// WORD IMAAlgorithBlockAlign
//
// Description:
// This function computes the standard block alignment that should
// be used given the WAVEFORMATEX structure.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -