338 lines
17 KiB
C++
338 lines
17 KiB
C++
/*-========================================================================-_
|
|
| - XAPO - |
|
|
| Copyright (c) Microsoft Corporation. All rights reserved. |
|
|
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
|
|
|PROJECT: XAPO MODEL: Unmanaged User-mode |
|
|
|VERSION: 1.0 EXCEPT: No Exceptions |
|
|
|CLASS: N / A MINREQ: WinXP, Xbox360 |
|
|
|BASE: N / A DIALECT: MSC++ 14.00 |
|
|
|>------------------------------------------------------------------------<|
|
|
| DUTY: XAPO base classes |
|
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
|
|
NOTES:
|
|
1. See XAPO.h for the rules governing XAPO interface behaviour. */
|
|
|
|
#pragma once
|
|
//--------------<D-E-F-I-N-I-T-I-O-N-S>-------------------------------------//
|
|
#include "XAPO.h"
|
|
|
|
// default audio format ranges supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat
|
|
#define XAPOBASE_DEFAULT_FORMAT_TAG WAVE_FORMAT_IEEE_FLOAT // 32-bit float only, applies to WAVEFORMATEX.wFormatTag or WAVEFORMATEXTENSIBLE.SubFormat when used
|
|
#define XAPOBASE_DEFAULT_FORMAT_MIN_CHANNELS XAPO_MIN_CHANNELS // minimum channel count, applies to WAVEFORMATEX.nChannels
|
|
#define XAPOBASE_DEFAULT_FORMAT_MAX_CHANNELS XAPO_MAX_CHANNELS // maximum channel count, applies to WAVEFORMATEX.nChannels
|
|
#define XAPOBASE_DEFAULT_FORMAT_MIN_FRAMERATE XAPO_MIN_FRAMERATE // minimum framerate, applies to WAVEFORMATEX.nSamplesPerSec
|
|
#define XAPOBASE_DEFAULT_FORMAT_MAX_FRAMERATE XAPO_MAX_FRAMERATE // maximum framerate, applies to WAVEFORMATEX.nSamplesPerSec
|
|
#define XAPOBASE_DEFAULT_FORMAT_BITSPERSAMPLE 32 // 32-bit float only, applies to WAVEFORMATEX.wBitsPerSample and WAVEFORMATEXTENSIBLE.wValidBitsPerSample when used
|
|
|
|
// default XAPO property flags supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS
|
|
#define XAPOBASE_DEFAULT_FLAG (XAPO_FLAG_CHANNELS_MUST_MATCH | XAPO_FLAG_FRAMERATE_MUST_MATCH | XAPO_FLAG_BITSPERSAMPLE_MUST_MATCH | XAPO_FLAG_BUFFERCOUNT_MUST_MATCH | XAPO_FLAG_INPLACE_SUPPORTED)
|
|
|
|
// default number of input and output buffers supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS
|
|
#define XAPOBASE_DEFAULT_BUFFER_COUNT 1
|
|
|
|
|
|
//--------------<M-A-C-R-O-S>-----------------------------------------------//
|
|
// assertion
|
|
#if !defined(XAPOASSERT)
|
|
#if XAPODEBUG
|
|
#define XAPOASSERT(exp) if (!(exp)) { OutputDebugStringA("XAPO ASSERT: " #exp ", {" __FUNCTION__ "}\n"); __debugbreak(); }
|
|
#else
|
|
#define XAPOASSERT(exp) __assume(exp)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
//--------------<D-A-T-A---T-Y-P-E-S>---------------------------------------//
|
|
#pragma pack(push, 8) // set packing alignment to ensure consistency across arbitrary build environments, and ensure synchronization variables used by Interlocked functionality are correctly aligned
|
|
|
|
|
|
// primitive types
|
|
typedef float FLOAT32; // 32-bit IEEE float
|
|
|
|
|
|
////
|
|
// DESCRIPTION:
|
|
// Default implementation of the IXAPO and IUnknown interfaces.
|
|
// Provides overridable implementations for all methods save IXAPO::Process.
|
|
////
|
|
class __declspec(novtable) CXAPOBase: public IXAPO {
|
|
private:
|
|
const XAPO_REGISTRATION_PROPERTIES* m_pRegistrationProperties; // pointer to registration properties of the XAPO, set via constructor
|
|
|
|
void* m_pfnMatrixMixFunction; // optimal matrix function pointer, used for thru processing
|
|
FLOAT32* m_pfl32MatrixCoefficients; // matrix coefficient table, used for thru processing
|
|
UINT32 m_nSrcFormatType; // input format type, used for thru processing
|
|
BOOL m_fIsScalarMatrix; // TRUE if m_pfl32MatrixCoefficients is diagonal matrix with all main diagonal entries equal, i.e. m_pfnMatrixMixFunction only used for type conversion (no channel conversion), used for thru processing
|
|
BOOL m_fIsLocked; // TRUE if XAPO locked via CXAPOBase.LockForProcess
|
|
|
|
|
|
protected:
|
|
LONG m_lReferenceCount; // COM reference count, must be aligned for atomic operations
|
|
|
|
////
|
|
// DESCRIPTION:
|
|
// Verifies an audio format falls within the default ranges supported.
|
|
//
|
|
// REMARKS:
|
|
// If pFormat is unsupported, and fOverwrite is TRUE,
|
|
// pFormat is overwritten with the nearest format supported.
|
|
// Nearest meaning closest bit depth, framerate, and channel count,
|
|
// in that order of importance.
|
|
//
|
|
// PARAMETERS:
|
|
// pFormat - [in/out] audio format to examine
|
|
// fOverwrite - [in] TRUE to overwrite pFormat if audio format unsupported
|
|
//
|
|
// RETURN VALUE:
|
|
// COM error code, including:
|
|
// S_OK - audio format supported, pFormat left untouched
|
|
// XAPO_E_FORMAT_UNSUPPORTED - audio format unsupported, pFormat overwritten with nearest audio format supported if fOverwrite TRUE
|
|
// E_INVALIDARG - audio format invalid, pFormat left untouched
|
|
////
|
|
virtual HRESULT ValidateFormatDefault (__inout WAVEFORMATEX* pFormat, BOOL fOverwrite);
|
|
|
|
////
|
|
// DESCRIPTION:
|
|
// Verifies that an input/output format pair configuration is supported
|
|
// with respect to the XAPO property flags.
|
|
//
|
|
// REMARKS:
|
|
// If pRequestedFormat is unsupported, and fOverwrite is TRUE,
|
|
// pRequestedFormat is overwritten with the nearest format supported.
|
|
// Nearest meaning closest bit depth, framerate, and channel count,
|
|
// in that order of importance.
|
|
//
|
|
// PARAMETERS:
|
|
// pSupportedFormat - [in] audio format known to be supported
|
|
// pRequestedFormat - [in/out] audio format to examine, must be WAVEFORMATEXTENSIBLE if fOverwrite TRUE
|
|
// fOverwrite - [in] TRUE to overwrite pRequestedFormat if input/output configuration unsupported
|
|
//
|
|
// RETURN VALUE:
|
|
// COM error code, including:
|
|
// S_OK - input/output configuration supported, pRequestedFormat left untouched
|
|
// XAPO_E_FORMAT_UNSUPPORTED - input/output configuration unsupported, pRequestedFormat overwritten with nearest audio format supported if fOverwrite TRUE
|
|
// E_INVALIDARG - either audio format invalid, pRequestedFormat left untouched
|
|
////
|
|
HRESULT ValidateFormatPair (const WAVEFORMATEX* pSupportedFormat, __inout WAVEFORMATEX* pRequestedFormat, BOOL fOverwrite);
|
|
|
|
////
|
|
// DESCRIPTION:
|
|
// This method may be called by an IXAPO::Process implementation
|
|
// for thru processing. It copies/mixes data from source to
|
|
// destination, making as few changes as possible to the audio data.
|
|
//
|
|
// REMARKS:
|
|
// However, this method is capable of channel upmix/downmix and uses
|
|
// the same matrix coefficient table used by windows Vista to do so.
|
|
//
|
|
// For in-place processing (input buffer == output buffer)
|
|
// this method does nothing.
|
|
//
|
|
// This method should be called only if the XAPO is locked and
|
|
// XAPO_FLAG_FRAMERATE_MUST_MATCH is used.
|
|
//
|
|
// PARAMETERS:
|
|
// pInputBuffer - [in] input buffer, format may be INT8, INT16, INT20 (contained in 24 or 32 bits), INT24 (contained in 24 or 32 bits), INT32, or FLOAT32
|
|
// pOutputBuffer - [out] output buffer, format must be FLOAT32
|
|
// FrameCount - [in] number of frames to process
|
|
// InputChannelCount - [in] number of input channels
|
|
// OutputChannelCount - [in] number of output channels
|
|
// MixWithOutput - [in] TRUE to mix with output, FALSE to overwrite output
|
|
//
|
|
// RETURN VALUE:
|
|
// void
|
|
////
|
|
void ProcessThru (__in void* pInputBuffer, __inout FLOAT32* pOutputBuffer, UINT32 FrameCount, WORD InputChannelCount, WORD OutputChannelCount, BOOL MixWithOutput);
|
|
|
|
// accessors
|
|
const XAPO_REGISTRATION_PROPERTIES* GetRegistrationPropertiesInternal () { return m_pRegistrationProperties; }
|
|
BOOL IsLocked () { return m_fIsLocked; }
|
|
|
|
|
|
public:
|
|
CXAPOBase (const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties);
|
|
virtual ~CXAPOBase ();
|
|
|
|
// IUnknown methods:
|
|
// retrieves the requested interface pointer if supported
|
|
STDMETHOD(QueryInterface) (REFIID riid, __deref_out_opt void** ppInterface)
|
|
{
|
|
XAPOASSERT(ppInterface != NULL);
|
|
HRESULT hr = S_OK;
|
|
|
|
if (riid == __uuidof(IXAPO)) {
|
|
*ppInterface = static_cast<IXAPO*>(this);
|
|
AddRef();
|
|
} else if (riid == __uuidof(IUnknown)) {
|
|
*ppInterface = static_cast<IUnknown*>(this);
|
|
AddRef();
|
|
} else {
|
|
*ppInterface = NULL;
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// increments reference count
|
|
STDMETHOD_(ULONG, AddRef) ()
|
|
{
|
|
return (ULONG)InterlockedIncrement(&m_lReferenceCount);
|
|
}
|
|
|
|
// decrements reference count and deletes the object if the reference count falls to zero
|
|
STDMETHOD_(ULONG, Release) ()
|
|
{
|
|
ULONG uTmpReferenceCount = (ULONG)InterlockedDecrement(&m_lReferenceCount);
|
|
if (uTmpReferenceCount == 0) {
|
|
delete this;
|
|
}
|
|
return uTmpReferenceCount;
|
|
}
|
|
|
|
// IXAPO methods:
|
|
// Allocates a copy of the registration properties of the XAPO.
|
|
// This default implementation returns a copy of the registration
|
|
// properties given to the constructor, allocated via XAPOAlloc.
|
|
STDMETHOD(GetRegistrationProperties) (__deref_out XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties);
|
|
|
|
// Queries if a specific input format is supported for a given output format.
|
|
// This default implementation assumes only the format described by the
|
|
// XAPOBASE_DEFAULT_FORMAT values are supported for both input and output.
|
|
STDMETHOD(IsInputFormatSupported) (const WAVEFORMATEX* pOutputFormat, const WAVEFORMATEX* pRequestedInputFormat, __deref_opt_out WAVEFORMATEX** ppSupportedInputFormat);
|
|
|
|
// Queries if a specific output format is supported for a given input format.
|
|
// This default implementation assumes only the format described by the
|
|
// XAPOBASE_DEFAULT_FORMAT values are supported for both input and output.
|
|
STDMETHOD(IsOutputFormatSupported) (const WAVEFORMATEX* pInputFormat, const WAVEFORMATEX* pRequestedOutputFormat, __deref_opt_out WAVEFORMATEX** ppSupportedOutputFormat);
|
|
|
|
// Performs any effect-specific initialization.
|
|
// This default implementation is a no-op and only returns S_OK.
|
|
STDMETHOD(Initialize) (__in_bcount_opt(DataByteSize) const void*, UINT32 DataByteSize)
|
|
{
|
|
UNREFERENCED_PARAMETER(DataByteSize);
|
|
return S_OK;
|
|
}
|
|
|
|
// Resets variables dependent on frame history.
|
|
// This default implementation is a no-op: this base class contains no
|
|
// relevant state to reset.
|
|
STDMETHOD_(void, Reset) () { return; }
|
|
|
|
// Notifies XAPO of buffer formats Process() will be given.
|
|
// This default implementation performs basic input/output format
|
|
// validation against the XAPO's registration properties.
|
|
// Derived XAPOs should call the base implementation first.
|
|
STDMETHOD(LockForProcess) (UINT32 InputLockedParameterCount, __in_ecount_opt(InputLockedParameterCount) const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters, UINT32 OutputLockedParameterCount, __in_ecount_opt(OutputLockedParameterCount) const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters);
|
|
|
|
// Opposite of LockForProcess.
|
|
// Derived XAPOs should call the base implementation first.
|
|
STDMETHOD_(void, UnlockForProcess) ();
|
|
|
|
// Returns the number of input frames required to generate the requested number of output frames.
|
|
// By default, this method returns the same number of frames it was passed.
|
|
STDMETHOD_(UINT32, CalcInputFrames) (UINT32 OutputFrameCount) { return OutputFrameCount; }
|
|
|
|
// Returns the number of output frames generated for the requested number of input frames.
|
|
// By default, this method returns the same number of frames it was passed.
|
|
STDMETHOD_(UINT32, CalcOutputFrames) (UINT32 InputFrameCount) { return InputFrameCount; }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------//
|
|
////
|
|
// DESCRIPTION:
|
|
// Extends CXAPOBase, providing a default implementation of the
|
|
// IXAPOParameters interface with appropriate synchronization to
|
|
// protect variables shared between IXAPOParameters::GetParameters
|
|
// and IXAPOParameters::SetParameters/IXAPO::Process.
|
|
//
|
|
// This class is for parameter blocks whose size is larger than 4 bytes.
|
|
// For smaller parameter blocks, use atomic operations directly
|
|
// on the parameters for synchronization.
|
|
////
|
|
class __declspec(novtable) CXAPOParametersBase: public CXAPOBase, public IXAPOParameters {
|
|
private:
|
|
BYTE* m_pParameterBlocks; // three contiguous process parameter blocks used for synchronization, user responsible for initialization of parameter blocks before IXAPO::Process/SetParameters/GetParameters called
|
|
BYTE* m_pCurrentParameters; // pointer to current process parameters, must be aligned for atomic operations
|
|
BYTE* m_pCurrentParametersInternal; // pointer to current process parameters (temp pointer read by SetParameters/BeginProcess/EndProcess)
|
|
UINT32 m_uCurrentParametersIndex; // index of current process parameters
|
|
UINT32 m_uParameterBlockByteSize; // size of a single parameter block in bytes, must be > 0
|
|
BOOL m_fNewerResultsReady; // TRUE if there exists new processing results not yet picked up by GetParameters(), must be aligned for atomic operations
|
|
BOOL m_fProducer; // IXAPO::Process produces data to be returned by GetParameters(); SetParameters() disallowed
|
|
|
|
|
|
public:
|
|
////
|
|
// PARAMETERS:
|
|
// pRegistrationProperties - [in] registration properties of the XAPO
|
|
// pParameterBlocks - [in] three contiguous process parameter blocks used for synchronization
|
|
// uParameterBlockByteSize - [in] size of one of the parameter blocks, must be > 0
|
|
// fProducer - [in] TRUE if IXAPO::Process produces data to be returned by GetParameters() (SetParameters() and ParametersChanged() disallowed)
|
|
////
|
|
CXAPOParametersBase (const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, BYTE* pParameterBlocks, UINT32 uParameterBlockByteSize, BOOL fProducer);
|
|
virtual ~CXAPOParametersBase ();
|
|
|
|
// IUnknown methods:
|
|
// retrieves the requested interface pointer if supported
|
|
STDMETHOD(QueryInterface) (REFIID riid, __deref_out_opt void** ppInterface)
|
|
{
|
|
XAPOASSERT(ppInterface != NULL);
|
|
HRESULT hr = S_OK;
|
|
|
|
if (riid == __uuidof(IXAPOParameters)) {
|
|
*ppInterface = static_cast<IXAPOParameters*>(this);
|
|
CXAPOBase::AddRef();
|
|
} else {
|
|
hr = CXAPOBase::QueryInterface(riid, ppInterface);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// increments reference count
|
|
STDMETHOD_(ULONG, AddRef)() { return CXAPOBase::AddRef(); }
|
|
|
|
// decrements reference count and deletes the object if the reference count falls to zero
|
|
STDMETHOD_(ULONG, Release)() { return CXAPOBase::Release(); }
|
|
|
|
// IXAPOParameters methods:
|
|
// Sets effect-specific parameters.
|
|
// This method may only be called on the realtime audio processing thread.
|
|
STDMETHOD_(void, SetParameters) (__in_bcount(ParameterByteSize) const void* pParameters, UINT32 ParameterByteSize);
|
|
|
|
// Gets effect-specific parameters.
|
|
// This method may block and should not be called from the realtime thread.
|
|
// Get the current parameters via BeginProcess.
|
|
STDMETHOD_(void, GetParameters) (__out_bcount(ParameterByteSize) void* pParameters, UINT32 ParameterByteSize);
|
|
|
|
// Called by SetParameters() to allow for user-defined parameter validation.
|
|
// SetParameters validates that ParameterByteSize == m_uParameterBlockByteSize
|
|
// so the user may assume/assert ParameterByteSize == m_uParameterBlockByteSize.
|
|
// This method should not block as it is called from the realtime thread.
|
|
virtual void OnSetParameters (const void*, UINT32) { }
|
|
|
|
// Returns TRUE if SetParameters() has been called since the last processing pass.
|
|
// May only be used within the XAPO's IXAPO::Process implementation,
|
|
// before BeginProcess is called.
|
|
BOOL ParametersChanged ();
|
|
|
|
// Returns latest process parameters.
|
|
// XAPOs must call this method within their IXAPO::Process
|
|
// implementation to access latest process parameters in threadsafe manner.
|
|
BYTE* BeginProcess ();
|
|
|
|
// Notifies CXAPOParametersBase that the XAPO has finished accessing
|
|
// the latest process parameters.
|
|
// XAPOs must call this method within their IXAPO::Process
|
|
// implementation to access latest process parameters in threadsafe manner.
|
|
void EndProcess ();
|
|
};
|
|
|
|
|
|
#pragma pack(pop) // revert packing alignment
|
|
//---------------------------------<-EOF->----------------------------------//
|