XAPOBase.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*-========================================================================-_
  2. | - XAPO - |
  3. | Copyright (c) Microsoft Corporation. All rights reserved. |
  4. |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
  5. |PROJECT: XAPO MODEL: Unmanaged User-mode |
  6. |VERSION: 1.0 EXCEPT: No Exceptions |
  7. |CLASS: N / A MINREQ: WinXP, Xbox360 |
  8. |BASE: N / A DIALECT: MSC++ 14.00 |
  9. |>------------------------------------------------------------------------<|
  10. | DUTY: XAPO base classes |
  11. ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
  12. NOTES:
  13. 1. See XAPO.h for the rules governing XAPO interface behaviour. */
  14. #pragma once
  15. //--------------<D-E-F-I-N-I-T-I-O-N-S>-------------------------------------//
  16. #include "XAPO.h"
  17. // default audio format ranges supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat
  18. #define XAPOBASE_DEFAULT_FORMAT_TAG WAVE_FORMAT_IEEE_FLOAT // 32-bit float only, applies to WAVEFORMATEX.wFormatTag or WAVEFORMATEXTENSIBLE.SubFormat when used
  19. #define XAPOBASE_DEFAULT_FORMAT_MIN_CHANNELS XAPO_MIN_CHANNELS // minimum channel count, applies to WAVEFORMATEX.nChannels
  20. #define XAPOBASE_DEFAULT_FORMAT_MAX_CHANNELS XAPO_MAX_CHANNELS // maximum channel count, applies to WAVEFORMATEX.nChannels
  21. #define XAPOBASE_DEFAULT_FORMAT_MIN_FRAMERATE XAPO_MIN_FRAMERATE // minimum framerate, applies to WAVEFORMATEX.nSamplesPerSec
  22. #define XAPOBASE_DEFAULT_FORMAT_MAX_FRAMERATE XAPO_MAX_FRAMERATE // maximum framerate, applies to WAVEFORMATEX.nSamplesPerSec
  23. #define XAPOBASE_DEFAULT_FORMAT_BITSPERSAMPLE 32 // 32-bit float only, applies to WAVEFORMATEX.wBitsPerSample and WAVEFORMATEXTENSIBLE.wValidBitsPerSample when used
  24. // default XAPO property flags supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS
  25. #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)
  26. // default number of input and output buffers supported, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS
  27. #define XAPOBASE_DEFAULT_BUFFER_COUNT 1
  28. //--------------<M-A-C-R-O-S>-----------------------------------------------//
  29. // assertion
  30. #if !defined(XAPOASSERT)
  31. #if XAPODEBUG
  32. #define XAPOASSERT(exp) if (!(exp)) { OutputDebugStringA("XAPO ASSERT: " #exp ", {" __FUNCTION__ "}\n"); __debugbreak(); }
  33. #else
  34. #define XAPOASSERT(exp) __assume(exp)
  35. #endif
  36. #endif
  37. //--------------<D-A-T-A---T-Y-P-E-S>---------------------------------------//
  38. #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
  39. // primitive types
  40. typedef float FLOAT32; // 32-bit IEEE float
  41. ////
  42. // DESCRIPTION:
  43. // Default implementation of the IXAPO and IUnknown interfaces.
  44. // Provides overridable implementations for all methods save IXAPO::Process.
  45. ////
  46. class __declspec(novtable) CXAPOBase: public IXAPO {
  47. private:
  48. const XAPO_REGISTRATION_PROPERTIES* m_pRegistrationProperties; // pointer to registration properties of the XAPO, set via constructor
  49. void* m_pfnMatrixMixFunction; // optimal matrix function pointer, used for thru processing
  50. FLOAT32* m_pfl32MatrixCoefficients; // matrix coefficient table, used for thru processing
  51. UINT32 m_nSrcFormatType; // input format type, used for thru processing
  52. 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
  53. BOOL m_fIsLocked; // TRUE if XAPO locked via CXAPOBase.LockForProcess
  54. protected:
  55. LONG m_lReferenceCount; // COM reference count, must be aligned for atomic operations
  56. ////
  57. // DESCRIPTION:
  58. // Verifies an audio format falls within the default ranges supported.
  59. //
  60. // REMARKS:
  61. // If pFormat is unsupported, and fOverwrite is TRUE,
  62. // pFormat is overwritten with the nearest format supported.
  63. // Nearest meaning closest bit depth, framerate, and channel count,
  64. // in that order of importance.
  65. //
  66. // PARAMETERS:
  67. // pFormat - [in/out] audio format to examine
  68. // fOverwrite - [in] TRUE to overwrite pFormat if audio format unsupported
  69. //
  70. // RETURN VALUE:
  71. // COM error code, including:
  72. // S_OK - audio format supported, pFormat left untouched
  73. // XAPO_E_FORMAT_UNSUPPORTED - audio format unsupported, pFormat overwritten with nearest audio format supported if fOverwrite TRUE
  74. // E_INVALIDARG - audio format invalid, pFormat left untouched
  75. ////
  76. virtual HRESULT ValidateFormatDefault (__inout WAVEFORMATEX* pFormat, BOOL fOverwrite);
  77. ////
  78. // DESCRIPTION:
  79. // Verifies that an input/output format pair configuration is supported
  80. // with respect to the XAPO property flags.
  81. //
  82. // REMARKS:
  83. // If pRequestedFormat is unsupported, and fOverwrite is TRUE,
  84. // pRequestedFormat is overwritten with the nearest format supported.
  85. // Nearest meaning closest bit depth, framerate, and channel count,
  86. // in that order of importance.
  87. //
  88. // PARAMETERS:
  89. // pSupportedFormat - [in] audio format known to be supported
  90. // pRequestedFormat - [in/out] audio format to examine, must be WAVEFORMATEXTENSIBLE if fOverwrite TRUE
  91. // fOverwrite - [in] TRUE to overwrite pRequestedFormat if input/output configuration unsupported
  92. //
  93. // RETURN VALUE:
  94. // COM error code, including:
  95. // S_OK - input/output configuration supported, pRequestedFormat left untouched
  96. // XAPO_E_FORMAT_UNSUPPORTED - input/output configuration unsupported, pRequestedFormat overwritten with nearest audio format supported if fOverwrite TRUE
  97. // E_INVALIDARG - either audio format invalid, pRequestedFormat left untouched
  98. ////
  99. HRESULT ValidateFormatPair (const WAVEFORMATEX* pSupportedFormat, __inout WAVEFORMATEX* pRequestedFormat, BOOL fOverwrite);
  100. ////
  101. // DESCRIPTION:
  102. // This method may be called by an IXAPO::Process implementation
  103. // for thru processing. It copies/mixes data from source to
  104. // destination, making as few changes as possible to the audio data.
  105. //
  106. // REMARKS:
  107. // However, this method is capable of channel upmix/downmix and uses
  108. // the same matrix coefficient table used by windows Vista to do so.
  109. //
  110. // For in-place processing (input buffer == output buffer)
  111. // this method does nothing.
  112. //
  113. // This method should be called only if the XAPO is locked and
  114. // XAPO_FLAG_FRAMERATE_MUST_MATCH is used.
  115. //
  116. // PARAMETERS:
  117. // 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
  118. // pOutputBuffer - [out] output buffer, format must be FLOAT32
  119. // FrameCount - [in] number of frames to process
  120. // InputChannelCount - [in] number of input channels
  121. // OutputChannelCount - [in] number of output channels
  122. // MixWithOutput - [in] TRUE to mix with output, FALSE to overwrite output
  123. //
  124. // RETURN VALUE:
  125. // void
  126. ////
  127. void ProcessThru (__in void* pInputBuffer, __inout FLOAT32* pOutputBuffer, UINT32 FrameCount, WORD InputChannelCount, WORD OutputChannelCount, BOOL MixWithOutput);
  128. // accessors
  129. const XAPO_REGISTRATION_PROPERTIES* GetRegistrationPropertiesInternal () { return m_pRegistrationProperties; }
  130. BOOL IsLocked () { return m_fIsLocked; }
  131. public:
  132. CXAPOBase (const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties);
  133. virtual ~CXAPOBase ();
  134. // IUnknown methods:
  135. // retrieves the requested interface pointer if supported
  136. STDMETHOD(QueryInterface) (REFIID riid, __deref_out_opt void** ppInterface)
  137. {
  138. XAPOASSERT(ppInterface != NULL);
  139. HRESULT hr = S_OK;
  140. if (riid == __uuidof(IXAPO)) {
  141. *ppInterface = static_cast<IXAPO*>(this);
  142. AddRef();
  143. } else if (riid == __uuidof(IUnknown)) {
  144. *ppInterface = static_cast<IUnknown*>(this);
  145. AddRef();
  146. } else {
  147. *ppInterface = NULL;
  148. hr = E_NOINTERFACE;
  149. }
  150. return hr;
  151. }
  152. // increments reference count
  153. STDMETHOD_(ULONG, AddRef) ()
  154. {
  155. return (ULONG)InterlockedIncrement(&m_lReferenceCount);
  156. }
  157. // decrements reference count and deletes the object if the reference count falls to zero
  158. STDMETHOD_(ULONG, Release) ()
  159. {
  160. ULONG uTmpReferenceCount = (ULONG)InterlockedDecrement(&m_lReferenceCount);
  161. if (uTmpReferenceCount == 0) {
  162. delete this;
  163. }
  164. return uTmpReferenceCount;
  165. }
  166. // IXAPO methods:
  167. // Allocates a copy of the registration properties of the XAPO.
  168. // This default implementation returns a copy of the registration
  169. // properties given to the constructor, allocated via XAPOAlloc.
  170. STDMETHOD(GetRegistrationProperties) (__deref_out XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties);
  171. // Queries if a specific input format is supported for a given output format.
  172. // This default implementation assumes only the format described by the
  173. // XAPOBASE_DEFAULT_FORMAT values are supported for both input and output.
  174. STDMETHOD(IsInputFormatSupported) (const WAVEFORMATEX* pOutputFormat, const WAVEFORMATEX* pRequestedInputFormat, __deref_opt_out WAVEFORMATEX** ppSupportedInputFormat);
  175. // Queries if a specific output format is supported for a given input format.
  176. // This default implementation assumes only the format described by the
  177. // XAPOBASE_DEFAULT_FORMAT values are supported for both input and output.
  178. STDMETHOD(IsOutputFormatSupported) (const WAVEFORMATEX* pInputFormat, const WAVEFORMATEX* pRequestedOutputFormat, __deref_opt_out WAVEFORMATEX** ppSupportedOutputFormat);
  179. // Performs any effect-specific initialization.
  180. // This default implementation is a no-op and only returns S_OK.
  181. STDMETHOD(Initialize) (__in_bcount_opt(DataByteSize) const void*, UINT32 DataByteSize)
  182. {
  183. UNREFERENCED_PARAMETER(DataByteSize);
  184. return S_OK;
  185. }
  186. // Resets variables dependent on frame history.
  187. // This default implementation is a no-op: this base class contains no
  188. // relevant state to reset.
  189. STDMETHOD_(void, Reset) () { return; }
  190. // Notifies XAPO of buffer formats Process() will be given.
  191. // This default implementation performs basic input/output format
  192. // validation against the XAPO's registration properties.
  193. // Derived XAPOs should call the base implementation first.
  194. 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);
  195. // Opposite of LockForProcess.
  196. // Derived XAPOs should call the base implementation first.
  197. STDMETHOD_(void, UnlockForProcess) ();
  198. // Returns the number of input frames required to generate the requested number of output frames.
  199. // By default, this method returns the same number of frames it was passed.
  200. STDMETHOD_(UINT32, CalcInputFrames) (UINT32 OutputFrameCount) { return OutputFrameCount; }
  201. // Returns the number of output frames generated for the requested number of input frames.
  202. // By default, this method returns the same number of frames it was passed.
  203. STDMETHOD_(UINT32, CalcOutputFrames) (UINT32 InputFrameCount) { return InputFrameCount; }
  204. };
  205. //--------------------------------------------------------------------------//
  206. ////
  207. // DESCRIPTION:
  208. // Extends CXAPOBase, providing a default implementation of the
  209. // IXAPOParameters interface with appropriate synchronization to
  210. // protect variables shared between IXAPOParameters::GetParameters
  211. // and IXAPOParameters::SetParameters/IXAPO::Process.
  212. //
  213. // This class is for parameter blocks whose size is larger than 4 bytes.
  214. // For smaller parameter blocks, use atomic operations directly
  215. // on the parameters for synchronization.
  216. ////
  217. class __declspec(novtable) CXAPOParametersBase: public CXAPOBase, public IXAPOParameters {
  218. private:
  219. BYTE* m_pParameterBlocks; // three contiguous process parameter blocks used for synchronization, user responsible for initialization of parameter blocks before IXAPO::Process/SetParameters/GetParameters called
  220. BYTE* m_pCurrentParameters; // pointer to current process parameters, must be aligned for atomic operations
  221. BYTE* m_pCurrentParametersInternal; // pointer to current process parameters (temp pointer read by SetParameters/BeginProcess/EndProcess)
  222. UINT32 m_uCurrentParametersIndex; // index of current process parameters
  223. UINT32 m_uParameterBlockByteSize; // size of a single parameter block in bytes, must be > 0
  224. BOOL m_fNewerResultsReady; // TRUE if there exists new processing results not yet picked up by GetParameters(), must be aligned for atomic operations
  225. BOOL m_fProducer; // IXAPO::Process produces data to be returned by GetParameters(); SetParameters() disallowed
  226. public:
  227. ////
  228. // PARAMETERS:
  229. // pRegistrationProperties - [in] registration properties of the XAPO
  230. // pParameterBlocks - [in] three contiguous process parameter blocks used for synchronization
  231. // uParameterBlockByteSize - [in] size of one of the parameter blocks, must be > 0
  232. // fProducer - [in] TRUE if IXAPO::Process produces data to be returned by GetParameters() (SetParameters() and ParametersChanged() disallowed)
  233. ////
  234. CXAPOParametersBase (const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, BYTE* pParameterBlocks, UINT32 uParameterBlockByteSize, BOOL fProducer);
  235. virtual ~CXAPOParametersBase ();
  236. // IUnknown methods:
  237. // retrieves the requested interface pointer if supported
  238. STDMETHOD(QueryInterface) (REFIID riid, __deref_out_opt void** ppInterface)
  239. {
  240. XAPOASSERT(ppInterface != NULL);
  241. HRESULT hr = S_OK;
  242. if (riid == __uuidof(IXAPOParameters)) {
  243. *ppInterface = static_cast<IXAPOParameters*>(this);
  244. CXAPOBase::AddRef();
  245. } else {
  246. hr = CXAPOBase::QueryInterface(riid, ppInterface);
  247. }
  248. return hr;
  249. }
  250. // increments reference count
  251. STDMETHOD_(ULONG, AddRef)() { return CXAPOBase::AddRef(); }
  252. // decrements reference count and deletes the object if the reference count falls to zero
  253. STDMETHOD_(ULONG, Release)() { return CXAPOBase::Release(); }
  254. // IXAPOParameters methods:
  255. // Sets effect-specific parameters.
  256. // This method may only be called on the realtime audio processing thread.
  257. STDMETHOD_(void, SetParameters) (__in_bcount(ParameterByteSize) const void* pParameters, UINT32 ParameterByteSize);
  258. // Gets effect-specific parameters.
  259. // This method may block and should not be called from the realtime thread.
  260. // Get the current parameters via BeginProcess.
  261. STDMETHOD_(void, GetParameters) (__out_bcount(ParameterByteSize) void* pParameters, UINT32 ParameterByteSize);
  262. // Called by SetParameters() to allow for user-defined parameter validation.
  263. // SetParameters validates that ParameterByteSize == m_uParameterBlockByteSize
  264. // so the user may assume/assert ParameterByteSize == m_uParameterBlockByteSize.
  265. // This method should not block as it is called from the realtime thread.
  266. virtual void OnSetParameters (const void*, UINT32) { }
  267. // Returns TRUE if SetParameters() has been called since the last processing pass.
  268. // May only be used within the XAPO's IXAPO::Process implementation,
  269. // before BeginProcess is called.
  270. BOOL ParametersChanged ();
  271. // Returns latest process parameters.
  272. // XAPOs must call this method within their IXAPO::Process
  273. // implementation to access latest process parameters in threadsafe manner.
  274. BYTE* BeginProcess ();
  275. // Notifies CXAPOParametersBase that the XAPO has finished accessing
  276. // the latest process parameters.
  277. // XAPOs must call this method within their IXAPO::Process
  278. // implementation to access latest process parameters in threadsafe manner.
  279. void EndProcess ();
  280. };
  281. #pragma pack(pop) // revert packing alignment
  282. //---------------------------------<-EOF->----------------------------------//