Corrections, +XAPO

This commit is contained in:
Vincent Billet
2025-05-05 22:14:20 +02:00
parent 125b60aee0
commit b34a490c02
5 changed files with 583 additions and 53 deletions
+10 -10
View File
@@ -100,14 +100,14 @@ CALCULATE_FLAG :: enum u32 {
//--------------<D-A-T-A---T-Y-P-E-S>---------------------------------------//
VECTOR :: distinct [3]f32 // float 3D vector
// instance handle of precalculated constants
HANDLE :: distinct [HANDLE_BYTESIZE]byte
// Distance curve point:
// Defines a DSP setting at a given normalized distance.
DISTANCE_CURVE_POINT :: struct #packed {
Distance: f32, // normalized distance, must be within [0.0f, 1.0f]
Distance: f32, // normalized distance, must be within [0.0f, 1.0f]
DSPSetting: f32, // DSP setting
}
@@ -122,14 +122,14 @@ DISTANCE_CURVE_POINT :: struct {
// pPoints[k-1].DSPSetting + ((pPoints[k].DSPSetting-pPoints[k-1].DSPSetting) / (pPoints[k].Distance-pPoints[k-1].Distance)) * (pPoints[k].Distance-pPoints[k-1].Distance) != NAN or infinite values
// For all points in the distance curve where 1 <= k < PointCount.
DISTANCE_CURVE :: struct #packed {
pPoints: [^]DISTANCE_CURVE_POINT, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance
pPoints: [^]DISTANCE_CURVE_POINT, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance
PointCount: u32, // number of distance curve points, must be >= 2 as all distance curves must have at least two endpoints, defining DSP settings at 0.0f and 1.0f normalized distance
}
Default_LinearCurvePoints := [2]DISTANCE_CURVE_POINT{{0.0, 1.0}, {1.0, 0.0}}
Default_LinearCurve := DISTANCE_CURVE{&Default_LinearCurvePoints[0], 2}
CONE :: struct #packed {
InnerAngle: f32, // inner cone angle in radians, must be within [0.0f, TAU]
InnerAngle: f32, // inner cone angle in radians, must be within [0.0f, TAU]
OuterAngle: f32, // outer cone angle in radians, must be within [InnerAngle, TAU]
InnerVolume: f32, // volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used
@@ -146,7 +146,7 @@ Default_DirectionalCone := CONE{math.PI / 2, math.PI, 1.0, 0.708, 0.0, 0.25, 0.7
//
// The cone is directed by the listener's front orientation.
LISTENER :: struct #packed {
OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used
OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used
OrientTop: VECTOR, // orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used
Position: VECTOR, // position in user-defined world units, does not affect Velocity
@@ -175,7 +175,7 @@ LISTENER :: struct {
// Distance curve calculations are also with respect to the emitter base position, with the curves being calculated independently of each other.
// For instance, volume and LFE calculations do not affect one another.
EMITTER :: struct #packed {
pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality
pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality
OrientFront: VECTOR, // orientation of front direction, used only for emitter angle calculations or with multi-channel emitters for matrix calculations or single-channel emitters with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used
OrientTop: VECTOR, // orientation of top direction, used only with multi-channel emitters for matrix calculations, must be orthonormal with OrientFront when used
@@ -205,7 +205,7 @@ EMITTER :: struct {
//
// The user is responsible for allocating the matrix coefficient table, delay time array, and initializing the channel counts when used.
DSP_SETTINGS :: struct #packed {
pMatrixCoefficients: [^]f32, // [inout] matrix coefficient table, receives an array representing the volume level used to send from source channel S to destination channel D, stored as pMatrixCoefficients[SrcChannelCount * D + S], must have at least SrcChannelCount*DstChannelCount elements
pMatrixCoefficients: [^]f32, // [inout] matrix coefficient table, receives an array representing the volume level used to send from source channel S to destination channel D, stored as pMatrixCoefficients[SrcChannelCount * D + S], must have at least SrcChannelCount*DstChannelCount elements
pDelayTimes: [^]f32, // [inout] delay time array, receives delays for each destination channel in milliseconds, must have at least DstChannelCount elements (stereo final mix only)
SrcChannelCount: u32, // [in] number of source channels, must equal number of channels in respective emitter
DstChannelCount: u32, // [in] number of destination channels, must equal number of channels of the final mix
@@ -223,11 +223,11 @@ DSP_SETTINGS :: struct {
//--------------<F-U-N-C-T-I-O-N-S>-----------------------------------------//
@(default_calling_convention="cdecl", link_prefix="X3DAudio")
foreign xa2 {
foreign xa2 {
// initializes instance handle
Initialize :: proc(SpeakerChannelMask: SPEAKER_FLAGS, SpeedOfSound: f32, Instance: HANDLE) -> HRESULT ---
// calculates DSP settings with respect to 3D parameters
Calculate :: proc(Instance: HANDLE, #by_ptr pListener: LISTENER, #by_ptr pEmitter: EMITTER, Flags: CALCULATE_FLAGS, pDSPSettings: ^DSP_SETTINGS) ---
}
}
}
+377
View File
@@ -0,0 +1,377 @@
#+build windows
/* NOTES:
1. Definition of terms:
DSP: Digital Signal Processing.
CBR: Constant BitRate -- DSP that consumes a constant number of
input samples to produce an output sample.
For example, a 22kHz to 44kHz resampler is CBR DSP.
Even though the number of input to output samples differ,
the ratio between input to output rate remains constant.
All user-defined XAPOs are assumed to be CBR as
XAudio2 only allows CBR DSP to be added to an effect chain.
XAPO: Cross-platform Audio Processing Object --
a thin wrapper that manages DSP code, allowing it
to be easily plugged into an XAudio2 effect chain.
Frame: A block of samples, one per channel,
to be played simultaneously.
E.g. a mono stream has one sample per frame.
In-Place: Processing such that the input buffer equals the
output buffer (i.e. input data modified directly).
This form of processing is generally more efficient
than using separate memory for input and output.
However, an XAPO may not perform format conversion
when processing in-place.
2. XAPO member variables are divided into three classifications:
Immutable: Set once via IXAPO.Initialize and remain
constant during the lifespan of the XAPO.
Locked: May change before the XAPO is locked via
IXAPO.LockForProcess but remain constant
until IXAPO.UnlockForProcess is called.
Dynamic: May change from one processing pass to the next,
usually via IXAPOParameters.SetParameters.
XAPOs should assign reasonable defaults to their dynamic
variables during IXAPO.Initialize/LockForProcess so
that calling IXAPOParameters.SetParameters is not
required before processing begins.
When implementing an XAPO, determine the type of each variable and
initialize them in the appropriate method. Immutable variables are
generally preferable over locked which are preferable over dynamic.
That is, one should strive to minimize XAPO state changes for
best performance, maintainability, and ease of use.
3. To minimize glitches, the realtime audio processing thread must
not block. XAPO methods called by the realtime thread are commented
as non-blocking and therefore should not use blocking synchronization,
allocate memory, access the disk, etc. The XAPO interfaces were
designed to allow an effect implementer to move such operations
into other methods called on an application controlled thread.
4. Extending functionality is accomplished through the addition of new
COM interfaces. For example, if a new member is added to a parameter
structure, a new interface using the new structure should be added,
leaving the original interface unchanged.
This ensures consistent communication between future versions of
XAudio2 and various versions of XAPOs that may exist in an application.
5. All audio data is interleaved in XAudio2.
The default audio format for an effect chain is WAVE_FORMAT_IEEE_FLOAT.
6. User-defined XAPOs should assume all input and output buffers are
16-byte aligned.
7. See XAPOBase.odin for an XAPO base class which provides a default
implementation for most of the interface methods defined below. */
package windows_xaudio2
import win "core:sys/windows"
//--------------<D-E-F-I-N-I-T-I-O-N-S>-------------------------------------//
// XAPO error codes
FORMAT_UNSUPPORTED := win.MAKE_HRESULT(win.SEVERITY.ERROR, 0x897, 0x01) // requested audio format unsupported
// supported number of channels (samples per frame) range
XAPO_MIN_CHANNELS :: 1
XAPO_MAX_CHANNELS :: 64
// supported framerate range
XAPO_MIN_FRAMERATE :: 1000
XAPO_MAX_FRAMERATE :: 200000
// unicode string length, including terminator, used with XAPO_REGISTRATION_PROPERTIES
XAPO_REGISTRATION_STRING_LENGTH :: 256
// XAPO property flags, used with XAPO_REGISTRATION_PROPERTIES.Flags:
XAPO_FLAGS :: distinct bit_set[XAPO_FLAG; u32]
XAPO_FLAG :: enum u32 {
// Number of channels of input and output buffers must match, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat.
CHANNELS_MUST_MATCH = 0,
// Framerate of input and output buffers must match, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat.
FRAMERATE_MUST_MATCH = 1,
// Bit depth of input and output buffers must match, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat.
// Container size of input and output buffers must also match if XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat is WAVEFORMATEXTENSIBLE.
BITSPERSAMPLE_MUST_MATCH = 2,
// Number of input and output buffers must match, applies to XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.
// Also, XAPO_REGISTRATION_PROPERTIES.MinInputBufferCount must equal XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount and XAPO_REGISTRATION_PROPERTIES.MaxInputBufferCount must equal XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount when used.
BUFFERCOUNT_MUST_MATCH = 3,
// XAPO must be run in-place. Use this flag only if your DSP implementation cannot process separate input and output buffers.
// If set, the following flags must also be set:
// XAPO_FLAG_CHANNELS_MUST_MATCH
// XAPO_FLAG_FRAMERATE_MUST_MATCH
// XAPO_FLAG_BITSPERSAMPLE_MUST_MATCH
// XAPO_FLAG_BUFFERCOUNT_MUST_MATCH
// XAPO_FLAG_INPLACE_SUPPORTED
// Multiple input and output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count.
// When multiple input/output buffers are used, the XAPO may assume input buffer [N] equals output buffer [N] for in-place processing.
INPLACE_REQUIRED = 5,
// XAPO may be run in-place. If the XAPO is used in a chain such that the requirements for XAPO_FLAG_INPLACE_REQUIRED are met, XAudio2 will ensure the XAPO is run in-place.
// If not met, XAudio2 will still run the XAPO albeit with separate input and output buffers.
// For example, consider an effect which may be ran in stereo->5.1 mode or mono->mono mode. When set to stereo->5.1, it will be run with separate input and output buffers as format conversion is not permitted in-place.
// However, if configured to run mono->mono, the same XAPO can be run in-place. Thus the same implementation may be conveniently reused for various input/output configurations, while taking advantage of in-place processing when possible.
INPLACE_SUPPORTED = 4,
}
//--------------<D-A-T-A---T-Y-P-E-S>---------------------------------------//
// XAPO registration properties, describes general XAPO characteristics, used with IXAPO.GetRegistrationProperties
XAPO_REGISTRATION_PROPERTIES :: struct #packed {
clsid: win.CLSID, // COM class ID, used with CoCreate
FriendlyName: [XAPO_REGISTRATION_STRING_LENGTH]u16, // friendly name unicode string
CopyrightInfo: [XAPO_REGISTRATION_STRING_LENGTH]u16, // copyright information unicode string
MajorVersion: u32, // major version
MinorVersion: u32, // minor version
Flags: XAPO_FLAGS, // XAPO property flags, describes supported input/output configuration
MinInputBufferCount: u32, // minimum number of input buffers required for processing, can be 0
MaxInputBufferCount: u32, // maximum number of input buffers supported for processing, must be >= MinInputBufferCount
MinOutputBufferCount: u32, // minimum number of output buffers required for processing, can be 0, must match MinInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used
MaxOutputBufferCount: u32, // maximum number of output buffers supported for processing, must be >= MinOutputBufferCount, must match MaxInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used
}
// LockForProcess buffer parameters:
// Defines buffer parameters that remain constant while an XAPO is locked.
// Used with IXAPO::LockForProcess.
// For CBR XAPOs, MaxFrameCount is the only number of frames
// IXAPO::Process would have to handle for the respective buffer.
XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS :: struct #packed {
pFormat: ^WAVEFORMATEX, // buffer audio format
MaxFrameCount: u32, // maximum number of frames in respective buffer that IXAPO::Process would have to handle, irrespective of dynamic variable settings, can be 0
}
// Buffer flags:
// Describes assumed content of the respective buffer.
// Used with XAPO_PROCESS_BUFFER_PARAMETERS.BufferFlags.
// This meta-data can be used by an XAPO to implement optimizations that require knowledge of a buffer's content.
// For example, XAPOs that always produce silent output from silent input can check the flag on the input buffer to determine if any signal processing is necessary.
// If silent, the XAPO may simply set the flag on the output buffer to silent and return, optimizing out the work of processing silent data: XAPOs that generate silence for any reason may set the buffer's flag accordingly rather than writing out silent frames to the buffer itself.
// The flags represent what should be assumed is in the respective buffer. The flags may not reflect what is actually stored in memory.
XAPO_BUFFER_FLAGS :: enum i32 {
XAPO_BUFFER_SILENT, // silent data should be assumed, respective memory may be uninitialized
XAPO_BUFFER_VALID, // arbitrary data should be assumed (may or may not be silent frames), respective memory initialized
}
// Process buffer parameters:
// Defines buffer parameters that may change from one
// processing pass to the next. Used with IXAPO::Process.
//
// Note the byte size of the respective buffer must be at least:
// XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount * XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat->nBlockAlign
//
// Although the audio format and maximum size of the respective
// buffer is locked (defined by XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS),
// the actual memory address of the buffer given is permitted to change
// from one processing pass to the next.
//
// For CBR XAPOs, ValidFrameCount is constant while locked and equals
// the respective XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount.
XAPO_PROCESS_BUFFER_PARAMETERS :: struct #packed {
pBuffer: rawptr, // audio data buffer, must be non-NULL
BufferFlags: XAPO_BUFFER_FLAGS, // describes assumed content of pBuffer, does not affect ValidFrameCount
ValidFrameCount: u32, // number of frames of valid data, must be within respective [0, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount], always XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount for CBR/user-defined XAPOs, does not affect BufferFlags
}
XAPOFree :: win.CoTaskMemFree
IXAPO_UUID_STRING :: "A410B984-9839-4819-A0BE-2856AE6B3ADB"
IXAPO_UUID := &win.IID{0xA410B984, 0x9839, 0x4819, {0xA0, 0xBE, 0x28, 0x56, 0xAE, 0x6B, 0x3A, 0xDB}}
IXAPO :: struct #raw_union {
#subtype iunknown: IUnknown,
using ixapo_vtable: ^IXAPO_VTable,
}
IXAPO_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
// DESCRIPTION:
// Allocates a copy of the registration properties of the XAPO.
// PARAMETERS:
// ppRegistrationProperties - [out] receives pointer to copy of registration properties, use XAPOFree to free structure, left untouched on failure
// RETURN VALUE:
// COM error code
GetRegistrationProperties: proc "system" (this: ^IXAPO, ppRegistrationProperties: ^^XAPO_REGISTRATION_PROPERTIES) -> HRESULT,
// DESCRIPTION:
// Queries if an input/output configuration is supported.
// REMARKS:
// This method allows XAPOs to express dependency of input format with respect to output format.
// If the input/output format pair configuration is unsupported, this method also determines the nearest input format supported.
// Nearest meaning closest bit depth, framerate, and channel count, in that order of importance.
// The behaviour of this method should remain constant after the XAPO has been initialized.
// PARAMETERS:
// pOutputFormat - [in] output format known to be supported
// pRequestedInputFormat - [in] input format to examine
// ppSupportedInputFormat - [out] receives pointer to nearest input format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED
// RETURN VALUE:
// COM error code, including:
// S_OK - input/output configuration supported, ppSupportedInputFormat left untouched
// FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedInputFormat receives pointer to nearest input format supported if not NULL
// E_INVALIDARG - either audio format invalid, ppSupportedInputFormat left untouched
IsInputFormatSupported: proc "system" (this: ^IXAPO, pOutputFormat: ^WAVEFORMATEX, pRequestedInputFormat: ^WAVEFORMATEX, ppSupportedInputFormat: ^^WAVEFORMATEX) -> HRESULT,
// DESCRIPTION:
// Queries if an input/output configuration is supported.
// REMARKS:
// This method allows XAPOs to express dependency of output format with respect to input format.
// If the input/output format pair configuration is unsupported, this method also determines the nearest output format supported.
// Nearest meaning closest bit depth, framerate, and channel count, in that order of importance.
// The behaviour of this method should remain constant after the XAPO has been initialized.
// PARAMETERS:
// pInputFormat - [in] input format known to be supported
// pRequestedOutputFormat - [in] output format to examine
// ppSupportedOutputFormat - [out] receives pointer to nearest output format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED
// RETURN VALUE:
// COM error code, including:
// S_OK - input/output configuration supported, ppSupportedOutputFormat left untouched
// FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedOutputFormat receives pointer to nearest output format supported if not NULL
// E_INVALIDARG - either audio format invalid, ppSupportedOutputFormat left untouched
IsOutputFormatSupported: proc "system" (this: ^IXAPO, pInputFormat: ^WAVEFORMATEX, pRequestedOutputFormat: ^WAVEFORMATEX, ppSupportedOutputFormat: ^^WAVEFORMATEX) -> HRESULT,
// DESCRIPTION:
// Performs any effect-specific initialization if required.
// REMARKS:
// The contents of pData are defined by the XAPO.
// Immutable variables (constant during the lifespan of the XAPO) should be set once via this method.
// Once initialized, an XAPO cannot be initialized again.
// An XAPO should be initialized before passing it to XAudio2 as part of an effect chain. XAudio2 will not call this method; it exists for future content-driven initialization.
// PARAMETERS:
// pData - [in] effect-specific initialization parameters, may be NULL if DataByteSize == 0
// DataByteSize - [in] size of pData in bytes, may be 0 if pData is NULL
// RETURN VALUE:
// COM error code
Initialize: proc "system" (this: ^IXAPO, pData: rawptr, DataByteSize: u32) -> HRESULT,
// DESCRIPTION:
// Resets variables dependent on frame history.
// REMARKS:
// All other variables remain unchanged, including variables set by IXAPOParameters.SetParameters.
// For example, an effect with delay should zero out its delay line during this method, but should not reallocate anything as the
// XAPO remains locked with a constant input/output configuration. XAudio2 calls this method only if the XAPO is locked.
// This method should not block as it is called from the realtime thread.
// PARAMETERS:
// void
// RETURN VALUE:
// void
Reset: proc "system" (this: ^IXAPO),
// DESCRIPTION:
// Locks the XAPO to a specific input/output configuration,
// allowing it to do any final initialization before Process
// is called on the realtime thread.
// REMARKS:
// Once locked, the input/output configuration and any other locked variables remain constant until UnlockForProcess is called.
// XAPOs should assert the input/output configuration is supported and that any required effect-specific initialization is complete.
// IsInputFormatSupported, IsOutputFormatSupported, and Initialize should be called as necessary before this method is called.
// All internal memory buffers required for Process should be allocated by the time this method returns successfully as Process is non-blocking and should not allocate memory.
// Once locked, an XAPO cannot be locked again until UnLockForProcess is called.
// PARAMETERS:
// InputLockedParameterCount - [in] number of input buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinInputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxInputBufferCount]
// pInputLockedParameters - [in] array of input locked buffer parameter structures, may be NULL if InputLockedParameterCount == 0, otherwise must have InputLockedParameterCount elements
// OutputLockedParameterCount - [in] number of output buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount], must match InputLockedParameterCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used
// pOutputLockedParameters - [in] array of output locked buffer parameter structures, may be NULL if OutputLockedParameterCount == 0, otherwise must have OutputLockedParameterCount elements
// RETURN VALUE:
// COM error code
LockForProcess: proc "system" (this: ^IXAPO, InputLockedParameterCount: u32, pInputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS, OutputLockedParameterCount: u32, pOutputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS) -> HRESULT,
// DESCRIPTION:
// Opposite of LockForProcess. Variables allocated during LockForProcess should be deallocated by this method.
// REMARKS:
// Unlocking an XAPO allows an XAPO instance to be reused with different input/output configurations.
// PARAMETERS:
// void
// RETURN VALUE:
// void
UnlockForProcess: proc "system" (this: ^IXAPO),
// DESCRIPTION:
// Runs the XAPO's DSP code on the given input/output buffers.
// REMARKS:
// In addition to writing to the output buffers as appropriate, an XAPO must set the BufferFlags and ValidFrameCount members of all elements in pOutputProcessParameters accordingly.
// ppInputProcessParameters will not necessarily be the same as ppOutputProcessParameters for in-place processing, rather the pBuffer members of each will point to the same memory.
// Multiple input/output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count.
// When multiple input/output buffers are used with in-place XAPOs, the XAPO may assume input buffer [N] equals output buffer [N].
// When IsEnabled is FALSE, the XAPO should process thru. Thru processing means an XAPO should not apply its normal processing to the given input/output buffers during Process.
// It should instead pass data from input to output with as little modification possible. Effects that perform format conversion should continue to do so.
// The effect must ensure transitions between normal and thru processing do not introduce discontinuities into the signal.
// XAudio2 calls this method only if the XAPO is locked. This method should not block as it is called from the realtime thread.
// PARAMETERS:
// InputProcessParameterCount - [in] number of input buffers, matches respective InputLockedParameterCount parameter given to LockForProcess
// pInputProcessParameters - [in] array of input process buffer parameter structures, may be NULL if InputProcessParameterCount == 0, otherwise must have InputProcessParameterCount elements
// OutputProcessParameterCount - [in] number of output buffers, matches respective OutputLockedParameterCount parameter given to LockForProcess
// pOutputProcessParameters - [in/out] array of output process buffer parameter structures, may be NULL if OutputProcessParameterCount == 0, otherwise must have OutputProcessParameterCount elements
// IsEnabled - [in] TRUE to process normally, FALSE to process thru
// RETURN VALUE:
// void
Process: proc "system" (this: ^IXAPO, InputProcessParameterCount: u32, pInputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, OutputProcessParameterCount: u32, pOutputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, IsEnabled: b32),
// DESCRIPTION:
// Returns the number of input frames required to generate the requested number of output frames.
// REMARKS:
// XAudio2 may call this method to determine how many input frames an XAPO requires.
// This is constant for locked CBR XAPOs; this method need only be called once while an XAPO is locked.
// XAudio2 calls this method only if the XAPO is locked. This method should not block as it is called from the realtime thread.
// PARAMETERS:
// OutputFrameCount - [in] requested number of output frames, must be within respective [0, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount], always XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount for CBR/user-defined XAPOs
// RETURN VALUE:
// number of input frames required
CalcInputFrames: proc "system" (this: ^IXAPO, OutputFrameCount: u32) -> u32,
// DESCRIPTION:
// Returns the number of output frames generated for the requested number of input frames.
// REMARKS:
// XAudio2 may call this method to determine how many output frames an XAPO will generate. This is constant for locked CBR XAPOs; this method need only be called once while an XAPO is locked.
// XAudio2 calls this method only if the XAPO is locked. This method should not block as it is called from the realtime thread.
// PARAMETERS:
// InputFrameCount - [in] requested number of input frames, must be within respective [0, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount], always XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount for CBR/user-defined XAPOs
// RETURN VALUE:
// number of output frames generated
CalcOutputFrames: proc "system" (this: ^IXAPO, InputFrameCount: u32) -> u32,
}
// IXAPOParameters:
// Optional XAPO COM interface that allows an XAPO to use effect-specific parameters.
IXAPOParameters_UUID_STRING :: "26D95C66-80F2-499A-AD54-5AE7F01C6D98"
IXAPOParameters_UUID := &win.IID{0x26D95C66, 0x80F2, 0x499A, {0xAD, 0x54, 0x5A, 0xE7, 0xF0, 0x1C, 0x6D, 0x98}}
IXAPOParameters :: struct #raw_union {
#subtype iunknown: IUnknown,
using ixapoparameters_vtable: ^IXAPOParameters_VTable,
}
IXAPOParameters_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
// DESCRIPTION:
// Sets effect-specific parameters.
// REMARKS:
// This method may only be called on the realtime thread; no synchronization between it and IXAPO.Process is necessary.
// This method should not block as it is called from the realtime thread.
// PARAMETERS:
// pParameters - [in] effect-specific parameter block, must be != NULL
// ParameterByteSize - [in] size of pParameters in bytes, must be > 0
// RETURN VALUE:
// void
SetParameters: proc "system" (this: ^IXAPOParameters, pParameters: rawptr, ParameterByteSize: u32),
// DESCRIPTION:
// Gets effect-specific parameters.
// REMARKS:
// Unlike SetParameters, XAudio2 does not call this method on the realtime thread. Thus, the XAPO must protect variables shared with SetParameters/Process using appropriate synchronization.
// PARAMETERS:
// pParameters - [out] receives effect-specific parameter block, must be != NULL
// ParameterByteSize - [in] size of pParameters in bytes, must be > 0
// RETURN VALUE:
// void
GetParameters: proc "system" (this: ^IXAPOParameters, pParameters: rawptr, ParameterByteSize: u32),
}
}
+138
View File
@@ -0,0 +1,138 @@
#+build windows
package windows_xaudio2
import win "core:sys/windows"
foreign import xa2 "system:xaudio2.lib"
//--------------<D-E-F-I-N-I-T-I-O-N-S>-------------------------------------//
FXEQ_UUID_STRING :: "F5E01117-D6C4-485A-A3F5-695196F3DBFA"
FXEQ_UUID := &win.CLSID{0xF5E01117, 0xD6C4, 0x485A, {0xA3, 0xF5, 0x69, 0x51, 0x96, 0xF3, 0xDB, 0xFA}}
FXMasteringLimiter_UUID_STRING :: "C4137916-2BE1-46FD-8599-441536F49856"
FXMasteringLimiter_UUID := &win.CLSID{0xC4137916, 0x2BE1, 0x46FD, {0x85, 0x99, 0x44, 0x15, 0x36, 0xF4, 0x98, 0x56}}
FXReverb_UUID_STRING :: "7D9ACA56-CB68-4807-B632-B137352E8596"
FXReverb_UUID := &win.CLSID{0x7D9ACA56, 0xCB68, 0x4807, {0xB6, 0x32, 0xB1, 0x37, 0x35, 0x2E, 0x85, 0x96}}
FXEcho_UUID_STRING :: "5039D740-F736-449A-84D3-A56202557B87"
FXEcho_UUID := &win.CLSID{0x5039D740, 0xF736, 0x449A, {0x84, 0xD3, 0xA5, 0x62, 0x02, 0x55, 0x7B, 0x87}}
// EQ parameter bounds (inclusive), used with FXEQ:
FXEQ_MIN_FRAMERATE :: 22000
FXEQ_MAX_FRAMERATE :: 48000
FXEQ_MIN_FREQUENCY_CENTER :: 20.0
FXEQ_MAX_FREQUENCY_CENTER :: 20000.0
FXEQ_DEFAULT_FREQUENCY_CENTER_0 :: 100.0 // band 0
FXEQ_DEFAULT_FREQUENCY_CENTER_1 :: 800.0 // band 1
FXEQ_DEFAULT_FREQUENCY_CENTER_2 :: 2000.0 // band 2
FXEQ_DEFAULT_FREQUENCY_CENTER_3 :: 10000.0 // band 3
FXEQ_MIN_GAIN :: 0.126 // -18dB
FXEQ_MAX_GAIN :: 7.94 // +18dB
FXEQ_DEFAULT_GAIN :: 1.0 // 0dB change, all bands
FXEQ_MIN_BANDWIDTH :: 0.1
FXEQ_MAX_BANDWIDTH :: 2.0
FXEQ_DEFAULT_BANDWIDTH :: 1.0 // all bands
// Mastering limiter parameter bounds (inclusive), used with FXMasteringLimiter:
FXMASTERINGLIMITER_MIN_RELEASE :: 1
FXMASTERINGLIMITER_MAX_RELEASE :: 20
FXMASTERINGLIMITER_DEFAULT_RELEASE :: 6
FXMASTERINGLIMITER_MIN_LOUDNESS :: 1
FXMASTERINGLIMITER_MAX_LOUDNESS :: 1800
FXMASTERINGLIMITER_DEFAULT_LOUDNESS :: 1000
// Reverb parameter bounds (inclusive), used with FXReverb:
FXREVERB_MIN_DIFFUSION :: 0.0
FXREVERB_MAX_DIFFUSION :: 1.0
FXREVERB_DEFAULT_DIFFUSION :: 0.9
FXREVERB_MIN_ROOMSIZE :: 0.0001
FXREVERB_MAX_ROOMSIZE :: 1.0
FXREVERB_DEFAULT_ROOMSIZE :: 0.6
// Loudness defaults used with FXLoudness:
FXLOUDNESS_DEFAULT_MOMENTARY_MS :: 400
FXLOUDNESS_DEFAULT_SHORTTERM_MS :: 3000
// Echo initialization data/parameter bounds (inclusive), used with FXEcho:
FXECHO_MIN_WETDRYMIX :: 0.0
FXECHO_MAX_WETDRYMIX :: 1.0
FXECHO_DEFAULT_WETDRYMIX :: 0.5
FXECHO_MIN_FEEDBACK :: 0.0
FXECHO_MAX_FEEDBACK :: 1.0
FXECHO_DEFAULT_FEEDBACK :: 0.5
FXECHO_MIN_DELAY :: 1.0
FXECHO_MAX_DELAY :: 2000.0
FXECHO_DEFAULT_DELAY :: 500.0
//--------------<D-A-T-A---T-Y-P-E-S>---------------------------------------//
// EQ parameters (4 bands), used with IXAPOParameters.SetParameters:
// The EQ supports only f32 audio foramts.
// The framerate must be within [22000, 48000] Hz.
FXEQ_PARAMETERS :: struct #packed {
FrequencyCenter0: f32, // center frequency in Hz, band 0
Gain0: f32, // boost/cut
Bandwidth0: f32, // bandwidth, region of EQ is center frequency +/- bandwidth/2
FrequencyCenter1: f32, // band 1
Gain1: f32,
Bandwidth1: f32,
FrequencyCenter2: f32, // band 2
Gain2: f32,
Bandwidth2: f32,
FrequencyCenter3: f32, // band 3
Gain3: f32,
Bandwidth3: f32,
}
// Mastering limiter parameters, used with IXAPOParameters.SetParameters:
// The mastering limiter supports only f32 audio formats.
FXMASTERINGLIMITER_PARAMETERS :: struct #packed {
Release: u32, // release time (tuning factor with no specific units)
Loudness: u32, // loudness target (threshold)
}
// Reverb parameters, used with IXAPOParameters.SetParameters:
// The reverb supports only f32 audio formats with the following channel configurations:
// Input: Mono Output: Mono
// Input: Stereo Output: Stereo
FXREVERB_PARAMETERS :: struct #packed {
Diffusion: f32, // diffusion
RoomSize: f32, // room size
};
// Echo initialization data, used with CreateFX:
// Use of this structure is optional, the default MaxDelay is FXECHO_DEFAULT_DELAY.
FXECHO_INITDATA :: struct #packed {
MaxDelay: f32, // maximum delay (all channels) in milliseconds, must be within [FXECHO_MIN_DELAY, FXECHO_MAX_DELAY]
}
// Echo parameters, used with IXAPOParameters.SetParameters:
// The echo supports only f32 audio formats.
FXECHO_PARAMETERS :: struct #packed {
WetDryMix: f32, // ratio of wet (processed) signal to dry (original) signal
Feedback: f32, // amount of output fed back into input
Delay: f32, // delay (all channels) in milliseconds, must be within [FXECHO_MIN_DELAY, FXECHO_PARAMETERS.MaxDelay]
}
//--------------<F-U-N-C-T-I-O-N-S>-----------------------------------------//
@(default_calling_convention="cdecl")
foreign xa2 {
// creates instance of requested XAPO, use Release to free instance
// pInitData - [in] effect-specific initialization parameters, may be NULL if InitDataByteSize == 0
// InitDataByteSize - [in] size of pInitData in bytes, may be 0 if pInitData is NULL
CreateFX :: proc(clsid: win.REFCLSID, pEffect: ^^IUnknown, pInitDat: rawptr = nil, InitDataByteSize: u32 = 0) -> HRESULT ---
}
}
+50 -30
View File
@@ -16,7 +16,7 @@ foreign import xa2 "system:xaudio2.lib"
HRESULT :: win.HRESULT
IUnknown :: win.IUnknown
IUnknown_VTable :: win.IUnknown_VTable
IID :: win.IID
WAVEFORMATEX :: win.WAVEFORMATEX
/**************************************************************************
*
@@ -82,10 +82,10 @@ QUANTUM_DENOMINATOR :: 100 // in 10ms chunks (= 1/100 seconds)
QUANTUM_MS :: (1000.0 * QUANTUM_NUMERATOR / QUANTUM_DENOMINATOR)
// XAudio2 error codes
INVALID_CALL :: HRESULT(-0x7769FFFF) // An API call or one of its arguments was illegal
XMA_DECODER_ERROR :: HRESULT(-0x7769FFFE) // The XMA hardware suffered an unrecoverable error
XAPO_CREATION_FAILED :: HRESULT(-0x7769FFFD) // XAudio2 failed to initialize an XAPO effect
DEVICE_INVALIDATED :: HRESULT(-0x7769FFFC) // An audio device became unusable (unplugged, etc)
INVALID_CALL :: HRESULT(-2003435519) // 0x88960001 An API call or one of its arguments was illegal
XMA_DECODER_ERROR :: HRESULT(-2003435518) // 0x88960002 The XMA hardware suffered an unrecoverable error
XAPO_CREATION_FAILED :: HRESULT(-2003435517) // 0x88960003 XAudio2 failed to initialize an XAPO effect
DEVICE_INVALIDATED :: HRESULT(-2003435516) // 0x88960004 An audio device became unusable (unplugged, etc)
/**************************************************************************
@@ -134,7 +134,7 @@ PROCESOR_FLAG :: enum u32 {
USE_DEFAULT_PROCESSOR :: PROCESSOR_FLAGS{}
// Returned by IXAudio2Voice.GetVoiceDetails
VOICE_DETAILS :: struct {
VOICE_DETAILS :: struct #packed {
CreatingFlags: FLAGS,
ActiveFlags: FLAGS,
InputChannels: u32,
@@ -142,26 +142,26 @@ VOICE_DETAILS :: struct {
}
// Used in VOICE_SENDS below
SEND_DESCRIPTOR :: struct {
SEND_DESCRIPTOR :: struct #packed {
Flags: FLAGS, // Either 0 or SEND_USEFILTER.
pOutputVoice: ^IXAudio2Voice, // This send's destination voice.
}
// Used in the voice creation functions and in IXAudio2Voice.SetOutputVoices
VOICE_SENDS :: struct {
VOICE_SENDS :: struct #packed {
SendCount: u32, // Number of sends from this voice.
pSends: [^]SEND_DESCRIPTOR, // Array of SendCount send descriptors.
}
// Used in EFFECT_CHAIN below
EFFECT_DESCRIPTOR :: struct {
EFFECT_DESCRIPTOR :: struct #packed {
pEffect: ^IUnknown, // Pointer to the effect object's IUnknown interface.
InitialState: bool, // TRUE if the effect should begin in the enabled state.
InitialState: b32, // TRUE if the effect should begin in the enabled state.
OutputChannels: u32, // How many output channels the effect should produce.
}
// Used in the voice creation functions and in IXAudio2Voice.SetEffectChain
EFFECT_CHAIN :: struct {
EFFECT_CHAIN :: struct #packed {
EffectCount: u32, // Number of effects in this voice's effect chain.
pEffectDescriptors: [^]EFFECT_DESCRIPTOR, // Array of effect descriptors.
}
@@ -177,14 +177,14 @@ FILTER_TYPE :: enum i32 {
}
// Used in IXAudio2Voice.Set/GetFilterParameters and Set/GetOutputFilterParameters
FILTER_PARAMETERS :: struct {
FILTER_PARAMETERS :: struct #packed {
Type: FILTER_TYPE, // Filter type.
Frequency: f32, // Filter coefficient. Must be >= 0 and <= MAX_FILTER_FREQUENCY. See CutoffFrequencyToRadians() for state-variable filter types and CutoffFrequencyToOnePoleCoefficient() for one-pole filter types.
OneOverQ: f32, // Reciprocal of the filter's quality factor Q; must be > 0 and <= MAX_FILTER_ONEOVERQ. Has no effect for one-pole filters.
}
// Used in IXAudio2SourceVoice.SubmitSourceBuffer
BUFFER :: struct {
BUFFER :: struct #packed {
Flags: FLAGS, // Either 0 or END_OF_STREAM.
AudioBytes: u32, // Size of the audio data buffer in bytes.
pAudioData: [^]byte, // Pointer to the audio data buffer.
@@ -199,20 +199,20 @@ BUFFER :: struct {
// Used in IXAudio2SourceVoice.SubmitSourceBuffer when submitting XWMA data.
// NOTE: If an XWMA sound is submitted in more than one buffer, each buffer's pDecodedPacketCumulativeBytes[PacketCount-1] value must be subtracted from all the entries in the next buffer's pDecodedPacketCumulativeBytes array.
// And whether a sound is submitted in more than one buffer or not, the final buffer of the sound should use the END_OF_STREAM flag, or else the client must call IXAudio2SourceVoice.Discontinuity after submitting it.
BUFFER_WMA :: struct {
BUFFER_WMA :: struct #packed {
pDecodedPacketCumulativeBytes: [^]u32, // Decoded packet's cumulative size array. Each element is the number of bytes accumulated when the corresponding XWMA packet is decoded in order. The array must have PacketCount elements.
PacketCount: u32, // Number of XWMA packets submitted. Must be >= 1 and divide evenly into BUFFER.AudioBytes.
}
// Returned by IXAudio2SourceVoice.GetState
VOICE_STATE :: struct {
VOICE_STATE :: struct #packed {
pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or NULL if there are no buffers in the queue.
BuffersQueued: u32, // Number of buffers currently queued on the voice (including the one that is being processed).
SamplesPlayed: u64, // Total number of samples produced by the voice since it began processing the current audio stream. If VOICE_NOSAMPLESPLAYED is specified in the call to IXAudio2SourceVoice.GetState, this member will not be calculated, saving CPU.
}
// Returned by IXAudio2.GetPerformanceData
PERFORMANCE_DATA :: struct {
PERFORMANCE_DATA :: struct #packed {
// CPU usage information
AudioCyclesSinceLastQuery: u64, // CPU cycles spent on audio processing since the last call to StartEngine or GetPerformanceData.
TotalCyclesSinceLastQuery: u64, // Total CPU cycles elapsed since the last call (only counts the CPU XAudio2 is running on).
@@ -240,13 +240,13 @@ PERFORMANCE_DATA :: struct {
}
// Used in IXAudio2.SetDebugConfiguration
DEBUG_CONFIGURATION :: struct {
DEBUG_CONFIGURATION :: struct #packed {
TraceMask: DEBUG_CONFIG_FLAGS, // Bitmap of enabled debug message types.
BreakMask: DEBUG_CONFIG_FLAGS, // Message types that will break into the debugger.
LogThreadID: bool, // Whether to log the thread ID with each message.
LogFileline: bool, // Whether to log the source file and line number.
LogFunctionName: bool, // Whether to log the function name.
LogTiming: bool, // Whether to log message timestamps.
LogThreadID: b32, // Whether to log the thread ID with each message.
LogFileline: b32, // Whether to log the source file and line number.
LogFunctionName: b32, // Whether to log the function name.
LogTiming: b32, // Whether to log message timestamps.
}
// Values for the TraceMask and BreakMask bitmaps. Only ERRORS and WARNINGS are valid in BreakMask.
@@ -273,7 +273,7 @@ DEBUG_CONFIG_FLAG :: enum u32 {
**************************************************************************/
IXAudio2_UUID_STRING :: "2B02E3CF-2E0B-4ec3-BE45-1B2A3FE7210D"
IXAudio2_UUID := &IID{0x2B02E3CF, 0x2E0B, 0x4ec3, {0xBE, 0x45, 0x1B, 0x2A, 0x3F, 0xE7, 0x21, 0x0D}}
IXAudio2_UUID := &win.IID{0x2B02E3CF, 0x2E0B, 0x4ec3, {0xBE, 0x45, 0x1B, 0x2A, 0x3F, 0xE7, 0x21, 0x0D}}
IXAudio2 :: struct #raw_union {
#subtype iunknown: IUnknown,
using ixaudio2_vtable: ^IXAudio2_VTable,
@@ -303,7 +303,7 @@ IXAudio2_VTable :: struct {
// pCallback - Optional pointer to a client-provided callback interface.
// pSendList - Optional list of voices this voice should send audio to.
// pEffectChain - Optional list of effects to apply to the audio data.
CreateSourceVoice: proc "system" (this: ^IXAudio2, ppSourceVoice: ^^IXAudio2SourceVoice, pSourceFormat: ^win.WAVEFORMATEX, Flags: FLAGS = {}, MaxFrequencyRatio: f32 = DEFAULT_FREQ_RATIO, pCallback: ^IXAudio2VoiceCallback = nil, pSendList: [^]VOICE_SENDS = nil, pEffectChain: [^]EFFECT_CHAIN = nil) -> HRESULT,
CreateSourceVoice: proc "system" (this: ^IXAudio2, ppSourceVoice: ^^IXAudio2SourceVoice, pSourceFormat: ^WAVEFORMATEX, Flags: FLAGS = {}, MaxFrequencyRatio: f32 = DEFAULT_FREQ_RATIO, pCallback: ^IXAudio2VoiceCallback = nil, pSendList: [^]VOICE_SENDS = nil, pEffectChain: [^]EFFECT_CHAIN = nil) -> HRESULT,
// NAME: IXAudio2.CreateSubmixVoice
// DESCRIPTION: Creates and configures a submix voice.
@@ -361,7 +361,7 @@ IXAudio2_VTable :: struct {
// This interface extends IXAudio2 with additional functionality.
// Use IXAudio2.QueryInterface to obtain a pointer to this interface.
IXAudio2Extension_UUID_STRING :: "84ac29bb-d619-44d2-b197-e4acf7df3ed6"
IXAudio2Extension_UUID := &IID{0x84ac29bb, 0xd619, 0x44d2, {0xb1, 0x97, 0xe4, 0xac, 0xf7, 0xdf, 0x3e, 0xd6}}
IXAudio2Extension_UUID := &win.IID{0x84ac29bb, 0xd619, 0x44d2, {0xb1, 0x97, 0xe4, 0xac, 0xf7, 0xdf, 0x3e, 0xd6}}
IXAudio2Extension :: struct #raw_union {
#subtype iunknown: IUnknown,
using ixaudio2extension_vtable: ^IXAudio2Extension_VTable,
@@ -432,7 +432,7 @@ IXAudio2Voice_VTable :: struct {
// ARGUMENTS:
// EffectIndex - Index of an effect within this voice's effect chain.
// pEnabled - Returns the enabled/disabled state of the given effect.
GetEffectState: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, pEnabled: ^bool),
GetEffectState: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, pEnabled: ^b32),
// NAME: IXAudio2Voice.SetEffectParameters
// DESCRIPTION: Sets effect-specific parameters.
@@ -717,12 +717,32 @@ IXAudio2VoiceCallback_VTable :: struct {
*
**************************************************************************/
// We're an xaudio2 client
@(default_calling_convention="system", link_prefix="XAudio2")
foreign xa2 {
Create :: proc(ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Processor: PROCESSOR_FLAGS = USE_DEFAULT_PROCESSOR) -> HRESULT ---
}
Create :: proc "stdcall" (ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT {
CreateWithVersionInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS, a3: win.DWORD) -> HRESULT
CreateInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS) -> HRESULT
dll_Instance: win.HMODULE
create_with_version_info: CreateWithVersionInfoFunc
create_info: CreateInfoFunc
if dll_Instance == nil {
dll_Instance = win.LoadLibraryExW(win.L("xaudio2_9.dll"), nil, {.LOAD_LIBRARY_SEARCH_SYSTEM32})
if dll_Instance == nil {
return HRESULT(win.GetLastError())
}
create_with_version_info = cast(CreateWithVersionInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2CreateWithVersionInfo")
if create_with_version_info == nil {
create_info = cast(CreateInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2Create")
if create_info == nil {
return HRESULT(win.GetLastError())
}
}
}
if create_with_version_info != nil {
return create_with_version_info(ppXAudio2, Flags, XAudio2Processor, 0x0A000010)
}
return create_info(ppXAudio2, Flags, XAudio2Processor)
}
/**************************************************************************
*
+8 -13
View File
@@ -6,12 +6,6 @@ import "core:math"
foreign import xa2 "system:xaudio2.lib"
/**************************************************************************
CLSID_AudioVolumeMeter_UUID := &IID{0x4FC3B166, 0x972A, 0x40CF, {0xBC, 0x37, 0x7D, 0xB0, 0x3D, 0xB2, 0xFB, 0xA3}}
CLSID_AudioReverb_UUID_STRING :: "C2633B16-471B-4498-B8C5-4F0959E2EC09"
CLSID_AudioReverb_UUID := &IID{0xC2633B16, 0x471B, 0x4498, {0xB8, 0xC5, 0x4F, 0x09, 0x59, 0xE2, 0xEC, 0x09}}
/**************************************************************************
*
* Effect creation functions.
*
@@ -21,7 +15,7 @@ CLSID_AudioReverb_UUID := &IID{0xC2633B16, 0x471B, 0x4498, {0xB8, 0xC5, 0x4F, 0x
**************************************************************************/
@(default_calling_convention="system")
foreign xa2 {
foreign xa2 {
CreateAudioVolumeMeter :: proc(ppApo: ^^IUnknown) -> HRESULT ---
CreateAudioReverb :: proc(ppApo: ^^IUnknown) -> HRESULT ---
}
@@ -37,7 +31,7 @@ foreign xa2 {
// The user is responsible for allocating pPeakLevels, pRMSLevels, and initializing ChannelCount accordingly.
// The volume meter does not support SetEffectParameters().
VOLUMEMETER_LEVELS :: struct #packed {
pPeakLevels: [^]f32, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be NULL if pRMSLevls != NULL, otherwise must have at least ChannelCount elements.
pPeakLevels: [^]f32, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be NULL if pRMSLevls != NULL, otherwise must have at least ChannelCount elements.
pRMSLevels: [^]f32, // Root mean square levels table: receives RMS level for each channel over a processing pass, may be NULL if pPeakLevels != NULL, otherwise must have at least ChannelCount elements.
ChannelCount: u32, // Number of channels being processed by the volume meter APO
}
@@ -64,7 +58,7 @@ REVERB_MAX_FRAMERATE :: 48000
// REVERB_PARAMETERS: Native parameter set for the reverb effect
REVERB_PARAMETERS :: struct #packed {
// ratio of wet (processed) signal to dry (original) signal
// ratio of wet (processed) signal to dry (original) signal
WetDryMix: f32, // [0, 100] (percentage)
// Delay times
ReflectionsDelay: u32, // [0, 300] in ms
@@ -93,7 +87,7 @@ REVERB_PARAMETERS :: struct {
RoomSize: f32, // [1, 100] in feet
// component control
DisableLateField: b32, // TRUE to disable late field reflections
}
}
// Maximum, minimum and default values for the parameters above
REVERB_MIN_WET_DRY_MIX :: 0.0
@@ -160,11 +154,12 @@ REVERB_DEFAULT_REVERB_GAIN :: 0.0
REVERB_DEFAULT_DENSITY :: 100.0
REVERB_DEFAULT_ROOM_SIZE :: 100.0
REVERB_DEFAULT_DISABLE_LATE_FIELD: b32 : false
// REVERB_I3DL2_PARAMETERS: Parameter set compliant with the I3DL2 standard
REVERB_I3DL2_PARAMETERS :: struct #packed {
// ratio of wet (processed) signal to dry (original) signal
// ratio of wet (processed) signal to dry (original) signal
WetDryMix: f32, // [0, 100] (percentage)
// Standard I3DL2 parameters
@@ -222,7 +217,7 @@ I3DL2_PRESET_PLATE := REVERB_I3DL2_PARAMETERS{100.0, -1000, -200,0.0,
// ReverbConvertI3DL2ToNative: Utility function to map from I3DL2 to native parameters
ReverbConvertI3DL2ToNative :: proc "contextless" (pI3DL2: ^REVERB_I3DL2_PARAMETERS, pNative: ^REVERB_PARAMETERS, sevenDotOneReverb: b32 = true) {
reflectionsDelay: f32
reflectionsDelay: f32
reverbDelay: f32
// RoomRolloffFactor is ignored