|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
/***************************************************************************
* * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved. * * File: imaadpcm.h * Content: IMA ADPCM CODEC. * History: * Date By Reason * ==== == ====== * 04/29/01 dereks Created. * ****************************************************************************/
#ifndef __IMAADPCM_H__
#define __IMAADPCM_H__
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <ctype.h>
#include <mmreg.h>
#include <msacm.h>
#define XBOX_ADPCM_SAMPLES_PER_BLOCK 64
#define WAVE_FORMAT_XBOX_ADPCM 0x0069
#define IMAADPCM_BITS_PER_SAMPLE 4
#define IMAADPCM_HEADER_LENGTH 4
#define IMAADPCM_MAX_CHANNELS 2
#define IMAADPCM_PCM_BITS_PER_SAMPLE 16
#define NUMELMS(a) (sizeof(a) / sizeof(a[0]))
typedef const WAVEFORMATEX *LPCWAVEFORMATEX; typedef const IMAADPCMWAVEFORMAT *LPCIMAADPCMWAVEFORMAT;
#ifdef __cplusplus
//
// IMA ADPCM encoder function prototype
//
typedef BOOL (*LPFNIMAADPCMCONVERT)(LPBYTE pbSrc, LPBYTE pbDst, UINT cBlocks, UINT nBlockAlignment, UINT cSamplesPerBlock, LPINT pnStepIndexL, LPINT pnStepIndexR);
//
// Codec mode
//
enum CODEC_MODE { CODEC_MODE_DECODE, CODEC_MODE_ENCODE_NORMAL, CODEC_MODE_ENCODE_OPTIMIZE_WHOLE_FILE, CODEC_MODE_ENCODE_OPTIMIZE_EACH_BLOCK, };
//
// IMA ADPCM CODEC
//
class CImaAdpcmCodec { private: static const short m_asNextStep[16]; // Step increment array
static const short m_asStep[89]; // Step value array
IMAADPCMWAVEFORMAT m_wfxEncode; // Encoded format description
CODEC_MODE m_cmCodecMode; // Codec mode
int m_nStepIndexL; // Left-channel stepping index
int m_nStepIndexR; // Right-channel stepping index
LPFNIMAADPCMCONVERT m_pfnConvert; // Conversion function
public: CImaAdpcmCodec(void); ~CImaAdpcmCodec(void);
public: // Initialization
BOOL Initialize(LPCIMAADPCMWAVEFORMAT pwfxEncode, CODEC_MODE cmCodecMode);
// Size conversions
WORD GetEncodeAlignment(void); WORD GetDecodeAlignment(void); WORD GetSourceAlignment(void); WORD GetDestinationAlignment(void);
// Data conversions
BOOL Convert(LPCVOID pvSrc, LPVOID pvDst, UINT cBlocks); void Reset(void);
// Format descriptions
static void CreatePcmFormat(WORD nChannels, DWORD nSamplesPerSec, LPWAVEFORMATEX pwfxFormat); static void CreateImaAdpcmFormat(WORD nChannels, DWORD nSamplesPerSec, WORD nSamplesPerBlock, LPIMAADPCMWAVEFORMAT pwfxFormat);
static BOOL IsValidPcmFormat(LPCWAVEFORMATEX pwfxFormat); static BOOL IsValidImaAdpcmFormat(LPCIMAADPCMWAVEFORMAT pwfxFormat);
private: // En/decoded data alignment
static WORD CalculateEncodeAlignment(WORD nSamplesPerBlock, WORD nChannels); // Data conversion functions
static BOOL EncodeM16(LPBYTE pbSrc, LPBYTE pbDst, UINT cBlocks, UINT nBlockAlignment, UINT cSamplesPerBlock, LPINT pnStepIndexL, LPINT pnStepIndexR); static BOOL EncodeS16(LPBYTE pbSrc, LPBYTE pbDst, UINT cBlocks, UINT nBlockAlignment, UINT cSamplesPerBlock, LPINT pnStepIndexL, LPINT pnStepIndexR); static BOOL DecodeM16(LPBYTE pbSrc, LPBYTE pbDst, UINT cBlocks, UINT nBlockAlignment, UINT cSamplesPerBlock, LPINT pnStepIndexL, LPINT pnStepIndexR); static BOOL DecodeS16(LPBYTE pbSrc, LPBYTE pbDst, UINT cBlocks, UINT nBlockAlignment, UINT cSamplesPerBlock, LPINT pnStepIndexL, LPINT pnStepIndexR);
static int EncodeSample(int nInputSample, int *nPredictedSample, int nStepSize); static int DecodeSample(int nInputSample, int nPredictedSample, int nStepSize);
static int NextStepIndex(int nEncodedSample, int nStepIndex); static BOOL ValidStepIndex(int nStepIndex);
/*static ULONGLONG CalcDifference(LPDWORD pvBuffer1, LPDWORD pvBuffer2, DWORD dwLength);*/ ULONGLONG CalcDifference(LPBYTE pvBuffer1, LPBYTE pvBuffer2, UINT cBlocks, UINT cTotalBlocks, DWORD dwBlockSize); };
__inline WORD CImaAdpcmCodec::GetSourceAlignment(void) { return ( m_cmCodecMode == CODEC_MODE_DECODE ) ? GetEncodeAlignment() : GetDecodeAlignment(); }
__inline WORD CImaAdpcmCodec::GetDestinationAlignment(void) { return ( m_cmCodecMode == CODEC_MODE_DECODE ) ? GetDecodeAlignment() : GetEncodeAlignment(); }
__inline int CImaAdpcmCodec::NextStepIndex(int nEncodedSample, int nStepIndex) { nStepIndex += m_asNextStep[nEncodedSample];
if(nStepIndex < 0) { nStepIndex = 0; } else if(nStepIndex >= NUMELMS(m_asStep)) { nStepIndex = NUMELMS(m_asStep) - 1; }
return nStepIndex; }
__inline BOOL CImaAdpcmCodec::ValidStepIndex(int nStepIndex) { return (nStepIndex >= 0) && (nStepIndex < NUMELMS(m_asStep)); }
#endif // __cplusplus
#endif // __IMAADPCM_H__
|