-
Notifications
You must be signed in to change notification settings - Fork 3
/
XAPOBase.h
337 lines (282 loc) · 16.9 KB
/
XAPOBase.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/*-========================================================================-_
| - 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->----------------------------------//