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