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->----------------------------------// |