⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acm.c

📁 书中的主要程序文件。在打开例题的.dsw文件后,请读者在 tools菜单下的 Options 的 Directories 标签中选择 Executable files
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================;
//
//  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 + -