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
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
|
#+build windows
/*
Bindings for Windows XAudio2:
https://learn.microsoft.com/en-us/windows/win32/xaudio2/xaudio2-introduction
Compiling for Windows 10 RS5 (1809) and later
*/
package windows_xaudio2
import win "core:sys/windows"
import "core:math"
foreign import xa2 "system:xaudio2.lib"
HRESULT :: win.HRESULT
IUnknown :: win.IUnknown
IUnknown_VTable :: win.IUnknown_VTable
WAVEFORMATEX :: win.WAVEFORMATEX
/**************************************************************************
*
* XAudio2 constants, flags and error codes.
*
**************************************************************************/
// Numeric boundary values
MAX_BUFFER_BYTES :: 0x80000000 // Maximum bytes allowed in a source buffer
MAX_QUEUED_BUFFERS :: 64 // Maximum buffers allowed in a voice queue
MAX_BUFFERS_SYSTEM :: 2 // Maximum buffers allowed for system threads (Xbox 360 only)
MAX_AUDIO_CHANNELS :: 64 // Maximum channels in an audio stream
MIN_SAMPLE_RATE :: 1000 // Minimum audio sample rate supported
MAX_SAMPLE_RATE :: 200000 // Maximum audio sample rate supported
MAX_VOLUME_LEVEL :: 16777216.0 // Maximum acceptable volume level (2^24)
MIN_FREQ_RATIO :: (1.0 / 1024.0) // Minimum SetFrequencyRatio argument
MAX_FREQ_RATIO :: 1024.0 // Maximum MaxFrequencyRatio argument
DEFAULT_FREQ_RATIO :: 2.0 // Default MaxFrequencyRatio argument
MAX_FILTER_ONEOVERQ :: 1.5 // Maximum FILTER_PARAMETERS.OneOverQ
MAX_FILTER_FREQUENCY :: 1.0 // Maximum FILTER_PARAMETERS.Frequency
MAX_LOOP_COUNT :: 254 // Maximum non-infinite BUFFER.LoopCount
MAX_INSTANCES :: 8 // Maximum simultaneous XAudio2 objects on Xbox 360
// For XMA voices on Xbox 360 there is an additional restriction on the MaxFrequencyRatio argument and the voice's sample rate: the product of these numbers cannot exceed 600000 for one-channel voices or 300000 for voices with more than one channel.
MAX_RATIO_TIMES_RATE_XMA_MONO :: 600000
MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL :: 300000
// Numeric values with special meanings
COMMIT_NOW :: 0 // Used as an OperationSet argument
COMMIT_ALL :: 0 // Used in IXAudio2.CommitChanges
INVALID_OPSET :: 0xffffffff // Not allowed for OperationSet arguments
NO_LOOP_REGION :: 0 // Used in BUFFER.LoopCount
LOOP_INFINITE :: 255 // Used in BUFFER.LoopCount
DEFAULT_CHANNELS :: 0 // Used in CreateMasteringVoice
DEFAULT_SAMPLERATE :: 0 // Used in CreateMasteringVoice
// Flags
FLAGS :: distinct bit_set[FLAG; u32]
FLAG :: enum u32 {
DEBUG_ENGINE = 0, // Used in Create
VOICE_NOPITCH = 1, // Used in IXAudio2.CreateSourceVoice
VOICE_NOSRC = 2, // Used in IXAudio2.CreateSourceVoice
VOICE_USEFILTER = 3, // Used in IXAudio2.CreateSource/SubmixVoice
PLAY_TAILS = 5, // Used in IXAudio2SourceVoice.Stop
END_OF_STREAM = 6, // Used in BUFFER.Flags
SEND_USEFILTER = 7, // Used in SEND_DESCRIPTOR.Flags
VOICE_NOSAMPLESPLAYED = 8, // Used in IXAudio2SourceVoice.GetState
STOP_ENGINE_WHEN_IDLE = 13, // Used in Create to force the engine to Stop when no source voices are Started, and Start when a voice is Started
QUANTUM_1024 = 15, // Used in Create to specify nondefault processing quantum of 21.33 ms (1024 samples at 48KHz)
NO_VIRTUAL_AUDIO_CLIENT = 16, // Used in CreateMasteringVoice to create a virtual audio client
}
// Default parameters for the built-in filter
DEFAULT_FILTER_TYPE :: FILTER_TYPE.LowPassFilter
DEFAULT_FILTER_FREQUENCY :: MAX_FILTER_FREQUENCY
DEFAULT_FILTER_ONEOVERQ :: 1.0
// Internal XAudio2 constants
// The audio frame quantum can be calculated by reducing the fraction:
// SamplesPerAudioFrame / SamplesPerSecond
QUANTUM_NUMERATOR :: 1 // On Windows, XAudio2 processes audio
QUANTUM_DENOMINATOR :: 100 // in 10ms chunks (= 1/100 seconds)
QUANTUM_MS :: (1000.0 * QUANTUM_NUMERATOR / QUANTUM_DENOMINATOR)
// XAudio2 error codes
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)
/**************************************************************************
*
* XAudio2 structures and enumerations.
*
**************************************************************************/
// Used in Create, specifies which CPU(s) to use.
PROCESSOR_FLAGS :: distinct bit_set[PROCESSOR_FLAG; u32]
PROCESSOR_FLAG :: enum u32 {
Processor1 = 0,
Processor2 = 1,
Processor3 = 2,
Processor4 = 3,
Processor5 = 4,
Processor6 = 5,
Processor7 = 6,
Processor8 = 7,
Processor9 = 8,
Processor10 = 9,
Processor11 = 10,
Processor12 = 11,
Processor13 = 12,
Processor14 = 13,
Processor15 = 14,
Processor16 = 15,
Processor17 = 16,
Processor18 = 17,
Processor19 = 18,
Processor20 = 19,
Processor21 = 20,
Processor22 = 21,
Processor23 = 22,
Processor24 = 23,
Processor25 = 24,
Processor26 = 25,
Processor27 = 26,
Processor28 = 27,
Processor29 = 28,
Processor30 = 29,
Processor31 = 30,
Processor32 = 31,
}
//ANY_PROCESSOR :: 0xffffffff
USE_DEFAULT_PROCESSOR :: PROCESSOR_FLAGS{}
// Returned by IXAudio2Voice.GetVoiceDetails
VOICE_DETAILS :: struct #packed {
CreatingFlags: FLAGS,
ActiveFlags: FLAGS,
InputChannels: u32,
InputSampleRate: u32,
}
// Used in VOICE_SENDS below
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 #packed {
SendCount: u32, // Number of sends from this voice.
pSends: [^]SEND_DESCRIPTOR `fmt:"v,SendCount"`, // Array of SendCount send descriptors.
}
// Used in EFFECT_CHAIN below
EFFECT_DESCRIPTOR :: struct #packed {
pEffect: ^IUnknown, // Pointer to the effect object's IUnknown interface.
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 #packed {
EffectCount: u32, // Number of effects in this voice's effect chain.
pEffectDescriptors: [^]EFFECT_DESCRIPTOR `fmt:"v,EffectCount"`, // Array of effect descriptors.
}
// Used in FILTER_PARAMETERS below
FILTER_TYPE :: enum i32 {
LowPassFilter, // Attenuates frequencies above the cutoff frequency (state-variable filter).
BandPassFilter, // Attenuates frequencies outside a given range (state-variable filter).
HighPassFilter, // Attenuates frequencies below the cutoff frequency (state-variable filter).
NotchFilter, // Attenuates frequencies inside a given range (state-variable filter).
LowPassOnePoleFilter, // Attenuates frequencies above the cutoff frequency (one-pole filter, FILTER_PARAMETERS.OneOverQ has no effect)
HighPassOnePoleFilter, // Attenuates frequencies below the cutoff frequency (one-pole filter, FILTER_PARAMETERS.OneOverQ has no effect)
}
// Used in IXAudio2Voice.Set/GetFilterParameters and Set/GetOutputFilterParameters
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 #packed {
Flags: FLAGS, // Either 0 or END_OF_STREAM.
AudioBytes: u32, // Size of the audio data buffer in bytes.
pAudioData: [^]byte `fmt:"v,AudioBytes"`, // Pointer to the audio data buffer.
PlayBegin: u32, // First sample in this buffer to be played.
PlayLength: u32, // Length of the region to be played in samples, or 0 to play the whole buffer.
LoopBegin: u32, // First sample of the region to be looped.
LoopLength: u32, // Length of the desired loop region in samples, or 0 to loop the entire buffer.
LoopCount: u32, // Number of times to repeat the loop region, or LOOP_INFINITE to loop forever.
pContext: rawptr, // Context value to be passed back in callbacks.
}
// 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 #packed {
pDecodedPacketCumulativeBytes: [^]u32 `fmt:"v,PacketCount"`, // 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 #packed {
pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or nil 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 #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).
MinimumCyclesPerQuantum: u32, // Fewest CPU cycles spent processing any one audio quantum since the last call.
MaximumCyclesPerQuantum: u32, // Most CPU cycles spent processing any one audio quantum since the last call.
// Memory usage information
MemoryUsageInBytes: u32, // Total heap space currently in use.
// Audio latency and glitching information
CurrentLatencyInSamples: u32, // Minimum delay from when a sample is read from a source buffer to when it reaches the speakers.
GlitchesSinceEngineStarted: u32, // Audio dropouts since the engine was started.
// Data about XAudio2's current workload
ActiveSourceVoiceCount: u32, // Source voices currently playing.
TotalSourceVoiceCount: u32, // Source voices currently existing.
ActiveSubmixVoiceCount: u32, // Submix voices currently playing/existing.
ActiveResamplerCount: u32, // Resample xAPOs currently active.
ActiveMatrixMixCount: u32, // MatrixMix xAPOs currently active.
// Usage of the hardware XMA decoder (Xbox 360 only)
ActiveXmaSourceVoices: u32, // Number of source voices decoding XMA data.
ActiveXmaStreams: u32, // A voice can use more than one XMA stream.
}
// Used in IXAudio2.SetDebugConfiguration
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: 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.
// WARNINGS implies ERRORS, DETAIL implies INFO, and FUNC_CALLS implies API_CALLS.
// By default, TraceMask is ERRORS and WARNINGS and all the other settings are zero.
DEBUG_CONFIG_FLAGS :: distinct bit_set[DEBUG_CONFIG_FLAG; u32]
DEBUG_CONFIG_FLAG :: enum u32 {
ERRORS = 0, // For handled errors with serious effects.
WARNINGS = 1, // For handled errors that may be recoverable.
INFO = 2, // Informational chit-chat (e.g. state changes).
DETAIL = 3, // More detailed chit-chat.
API_CALLS = 4, // Public API function entries and exits.
FUNC_CALLS = 5, // Internal function entries and exits.
TIMING = 6, // Delays detected and other timing data.
LOCKS = 7, // Usage of critical sections and mutexes.
MEMORY = 8, // Memory heap usage information.
STREAMING = 12, // Audio streaming information.
}
/**************************************************************************
*
* IXAudio2: Top-level XAudio2 COM interface.
*
**************************************************************************/
IXAudio2_UUID_STRING :: "2B02E3CF-2E0B-4ec3-BE45-1B2A3FE7210D"
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,
}
IXAudio2_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
// NAME: IXAudio2.RegisterForCallbacks
// DESCRIPTION: Adds a new client to receive XAudio2's engine callbacks.
// ARGUMENTS:
// pCallback - Callback interface to be called during each processing pass.
RegisterForCallbacks: proc "system" (this: ^IXAudio2, pCallback: ^IXAudio2EngineCallback) -> HRESULT,
// NAME: IXAudio2.UnregisterForCallbacks
// DESCRIPTION: Removes an existing receiver of XAudio2 engine callbacks.
// ARGUMENTS:
// pCallback - Previously registered callback interface to be removed.
UnregisterForCallbacks: proc "system" (this: ^IXAudio2, pCallback: ^IXAudio2EngineCallback),
// NAME: IXAudio2.CreateSourceVoice
// DESCRIPTION: Creates and configures a source voice.
// ARGUMENTS:
// ppSourceVoice - Returns the new object's IXAudio2SourceVoice interface.
// pSourceFormat - Format of the audio that will be fed to the voice.
// Flags - VOICE flags specifying the source voice's behavior.
// MaxFrequencyRatio - Maximum SetFrequencyRatio argument to be allowed.
// 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: ^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.
// ARGUMENTS:
// ppSubmixVoice - Returns the new object's IXAudio2SubmixVoice interface.
// InputChannels - Number of channels in this voice's input audio data.
// InputSampleRate - Sample rate of this voice's input audio data.
// Flags - VOICE flags specifying the submix voice's behavior.
// ProcessingStage - Arbitrary number that determines the processing order.
// pSendList - Optional list of voices this voice should send audio to.
// pEffectChain - Optional list of effects to apply to the audio data.
CreateSubmixVoice: proc "system" (this: ^IXAudio2, ppSubmixVoice: ^^IXAudio2SubmixVoice, InputChannels: u32, InputSampleRate: u32, Flags: FLAGS = {}, ProcessingStage: u32 = 0, pSendList: [^]VOICE_SENDS = nil, pEffectChain: [^]EFFECT_CHAIN = nil) -> HRESULT,
// NAME: IXAudio2.CreateMasteringVoice
// DESCRIPTION: Creates and configures a mastering voice.
// ARGUMENTS:
// ppMasteringVoice - Returns the new object's IXAudio2MasteringVoice interface.
// InputChannels - Number of channels in this voice's input audio data.
// InputSampleRate - Sample rate of this voice's input audio data.
// Flags - VOICE flags specifying the mastering voice's behavior.
// szDeviceId - Identifier of the device to receive the output audio.
// pEffectChain - Optional list of effects to apply to the audio data.
// StreamCategory - The audio stream category to use for this mastering voice
CreateMasteringVoice: proc "system" (this: ^IXAudio2, ppMasteringVoice: ^^IXAudio2MasteringVoice, InputChannels: u32 = DEFAULT_CHANNELS, InputSampleRate: u32 = DEFAULT_SAMPLERATE, Flags: FLAGS = {}, szDeviceId: win.LPCWSTR = nil, pEffectChain: [^]EFFECT_CHAIN = nil, StreamCategory: AUDIO_STREAM_CATEGORY = .GameEffects) -> HRESULT,
// NAME: IXAudio2.:StartEngine
// DESCRIPTION: Creates and starts the audio processing thread.
StartEngine: proc "system" (this: ^IXAudio2) -> HRESULT,
// NAME: IXAudio2.StopEngine
// DESCRIPTION: Stops and destroys the audio processing thread.
StopEngine: proc "system" (this: ^IXAudio2),
// NAME: IXAudio2.CommitChanges
// DESCRIPTION: Atomically applies a set of operations previously tagged with a given identifier.
// ARGUMENTS:
// OperationSet - Identifier of the set of operations to be applied.
CommitChanges: proc "system" (this: ^IXAudio2, OperationSet: u32) -> HRESULT,
// NAME: IXAudio2.GetPerformanceData
// DESCRIPTION: Returns current resource usage details: memory, CPU, etc.
// ARGUMENTS:
// pPerfData - Returns the performance data structure.
GetPerformanceData: proc "system" (this: ^IXAudio2, pPerfData: ^PERFORMANCE_DATA),
// NAME: IXAudio2.SetDebugConfiguration
// DESCRIPTION: Configures XAudio2's debug output (in debug builds only).
// ARGUMENTS:
// pDebugConfiguration - Structure describing the debug output behavior.
// pReserved - Optional parameter; must be nil.
SetDebugConfiguration: proc "system" (this: ^IXAudio2, pDebugConfiguration: ^DEBUG_CONFIGURATION, pReserved: rawptr = nil),
}
// 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 := &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,
}
IXAudio2Extension_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
// NAME: IXAudio2Extension.GetProcessingQuantum
// DESCRIPTION: Returns the processing quantum
// quantumMilliseconds = (1000.0f * quantumNumerator / quantumDenominator)
// ARGUMENTS:
// quantumNumerator - Quantum numerator
// quantumDenominator - Quantum denominator
GetProcessingQuantum: proc "system" (this: ^IXAudio2Extension, quantumNumerator: ^u32, quantumDenominator: ^u32),
// NAME: IXAudio2Extension.GetProcessor
// DESCRIPTION: Returns the number of the processor used by XAudio2
// ARGUMENTS:
// processor - Non-zero Processor number
GetProcessor: proc "system" (this: ^IXAudio2Extension, processor: ^PROCESSOR_FLAGS),
}
/**************************************************************************
*
* IXAudio2Voice: Base voice management interface.
*
**************************************************************************/
IXAudio2Voice :: struct {
using ixaudio2voice_vtable: ^IXAudio2Voice_VTable,
}
IXAudio2Voice_VTable :: struct {
// NAME: IXAudio2Voice.GetVoiceDetails
// DESCRIPTION: Returns the basic characteristics of this voice.
// ARGUMENTS:
// pVoiceDetails - Returns the voice's details.
GetVoiceDetails: proc "system" (this: ^IXAudio2Voice, pVoiceDetails: ^VOICE_DETAILS),
// NAME: IXAudio2Voice.SetOutputVoices
// DESCRIPTION: Replaces the set of submix/mastering voices that receive this voice's output.
// ARGUMENTS:
// pSendList - Optional list of voices this voice should send audio to.
SetOutputVoices: proc "system" (this: ^IXAudio2Voice, pSendList: [^]VOICE_SENDS) -> HRESULT,
// NAME: IXAudio2Voice.SetEffectChain
// DESCRIPTION: Replaces this voice's current effect chain with a new one.
// ARGUMENTS:
// pEffectChain - Structure describing the new effect chain to be used.
SetEffectChain: proc "system" (this: ^IXAudio2Voice, pEffectChain: ^EFFECT_CHAIN) -> HRESULT,
// NAME: IXAudio2Voice.EnableEffect
// DESCRIPTION: Enables an effect in this voice's effect chain.
// ARGUMENTS:
// EffectIndex - Index of an effect within this voice's effect chain.
// OperationSet - Used to identify this call as part of a deferred batch.
EnableEffect: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.DisableEffect
// DESCRIPTION: Disables an effect in this voice's effect chain.
// ARGUMENTS:
// EffectIndex - Index of an effect within this voice's effect chain.
// OperationSet - Used to identify this call as part of a deferred batch.
DisableEffect: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetEffectState
// DESCRIPTION: Returns the running state of an effect.
// 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: ^b32),
// NAME: IXAudio2Voice.SetEffectParameters
// DESCRIPTION: Sets effect-specific parameters.
// REMARKS: Unlike IXAPOParameters.SetParameters, this method may be called from any thread. XAudio2 implements appropriate synchronization to copy the parameters to the realtime audio processing thread.
// ARGUMENTS:
// EffectIndex - Index of an effect within this voice's effect chain.
// pParameters - Pointer to an effect-specific parameters block.
// ParametersByteSize - Size of the pParameters array in bytes.
// OperationSet - Used to identify this call as part of a deferred batch.
SetEffectParameters: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, pParameters: rawptr, ParametersByteSize: u32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetEffectParameters
// DESCRIPTION: Obtains the current effect-specific parameters.
// ARGUMENTS:
// EffectIndex - Index of an effect within this voice's effect chain.
// pParameters - Returns the current values of the effect-specific parameters.
// ParametersByteSize - Size of the pParameters array in bytes.
GetEffectParameters: proc "system" (this: ^IXAudio2Voice, EffectIndex: u32, pParameters: rawptr, ParametersByteSize: u32) -> HRESULT,
// NAME: IXAudio2Voice.SetFilterParameters
// DESCRIPTION: Sets this voice's filter parameters.
// ARGUMENTS:
// pParameters - Pointer to the filter's parameter structure.
// OperationSet - Used to identify this call as part of a deferred batch.
SetFilterParameters: proc "system" (this: ^IXAudio2Voice, pParameters: ^FILTER_PARAMETERS, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetFilterParameters
// DESCRIPTION: Returns this voice's current filter parameters.
// ARGUMENTS:
// pParameters - Returns the filter parameters.
GetFilterParameters: proc "system" (this: ^IXAudio2Voice, pParameters: ^FILTER_PARAMETERS),
// NAME: IXAudio2Voice.SetOutputFilterParameters
// DESCRIPTION: Sets the filter parameters on one of this voice's sends.
// ARGUMENTS:
// pDestinationVoice - Destination voice of the send whose filter parameters will be set.
// pParameters - Pointer to the filter's parameter structure.
// OperationSet - Used to identify this call as part of a deferred batch.
SetOutputFilterParameters: proc "system" (this: ^IXAudio2Voice, pDestinationVoice: ^IXAudio2Voice, pParameters: ^FILTER_PARAMETERS, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetOutputFilterParameters
// DESCRIPTION: Returns the filter parameters from one of this voice's sends.
// ARGUMENTS:
// pDestinationVoice - Destination voice of the send whose filter parameters will be read.
// pParameters - Returns the filter parameters.
GetOutputFilterParameters: proc "system" (this: ^IXAudio2Voice, pDestinationVoice: ^IXAudio2Voice, pParameters: ^FILTER_PARAMETERS),
// NAME: IXAudio2Voice.SetVolume
// DESCRIPTION: Sets this voice's overall volume level.
// ARGUMENTS:
// Volume - New overall volume level to be used, as an amplitude factor.
// OperationSet - Used to identify this call as part of a deferred batch.
SetVolume: proc "system" (this: ^IXAudio2Voice, Volume: f32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetVolume
// DESCRIPTION: Obtains this voice's current overall volume level.
// ARGUMENTS:
// pVolume: Returns the voice's current overall volume level.
GetVolume: proc "system" (this: ^IXAudio2Voice, pVolume: ^f32),
// NAME: IXAudio2Voice.SetChannelVolumes
// DESCRIPTION: Sets this voice's per-channel volume levels.
// ARGUMENTS:
// Channels - Used to confirm the voice's channel count.
// pVolumes - Array of per-channel volume levels to be used.
// OperationSet - Used to identify this call as part of a deferred batch.
SetChannelVolumes: proc "system" (this: ^IXAudio2Voice, Channels: u32, pVolumes: [^]f32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetChannelVolumes
// DESCRIPTION: Returns this voice's current per-channel volume levels.
// ARGUMENTS:
// Channels - Used to confirm the voice's channel count.
// pVolumes - Returns an array of the current per-channel volume levels.
GetChannelVolumes: proc "system" (this: ^IXAudio2Voice, Channels: u32, pVolumes: [^]f32),
// NAME: IXAudio2Voice.SetOutputMatrix
// DESCRIPTION: Sets the volume levels used to mix from each channel of this voice's output audio to each channel of a given destination voice's input audio.
// ARGUMENTS:
// pDestinationVoice - The destination voice whose mix matrix to change.
// SourceChannels - Used to confirm this voice's output channel count (the number of channels produced by the last effect in the chain).
// DestinationChannels - Confirms the destination voice's input channels.
// pLevelMatrix - Array of [SourceChannels * DestinationChannels] send levels. The level used to send from source channel S to destination channel D should be in pLevelMatrix[S + SourceChannels * D].
// OperationSet - Used to identify this call as part of a deferred batch.
SetOutputMatrix: proc "system" (this: ^IXAudio2Voice, pDestinationVoice: ^IXAudio2Voice, SourceChannels: u32, DestinationChannels: u32, pLevelMatrix: [^]f32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2Voice.GetOutputMatrix
// DESCRIPTION: Obtains the volume levels used to send each channel of this voice's output audio to each channel of a given destination voice's input audio.
// ARGUMENTS:
// pDestinationVoice - The destination voice whose mix matrix to obtain.
// SourceChannels - Used to confirm this voice's output channel count (the number of channels produced by the last effect in the chain).
// DestinationChannels - Confirms the destination voice's input channels.
// pLevelMatrix - Array of send levels, as above.
GetOutputMatrix: proc "system" (this: ^IXAudio2Voice, pDestinationVoice: ^IXAudio2Voice, SourceChannels: u32, DestinationChannels: u32, pLevelMatrix: [^]f32),
// NAME: IXAudio2Voice.DestroyVoice
// DESCRIPTION: Destroys this voice, stopping it if necessary and removing it from the XAudio2 graph.
DestroyVoice: proc "system" (this: ^IXAudio2Voice),
}
/**************************************************************************
*
* IXAudio2SourceVoice: Source voice management interface.
*
**************************************************************************/
IXAudio2SourceVoice :: struct #raw_union {
#subtype ixaudio2voice: IXAudio2Voice,
using ixaudio2sourcevoice_vtable: ^IXAudio2SourceVoice_VTable,
}
IXAudio2SourceVoice_VTable :: struct {
using ixaudio2voice_vtable: IXAudio2Voice_VTable,
// NAME: IXAudio2SourceVoice.Start
// DESCRIPTION: Makes this voice start consuming and processing audio.
// ARGUMENTS:
// Flags - Flags controlling how the voice should be started.
// OperationSet - Used to identify this call as part of a deferred batch.
Start: proc "system" (this: ^IXAudio2SourceVoice, Flags: FLAGS = {}, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2SourceVoice.Stop
// DESCRIPTION: Makes this voice stop consuming audio.
// ARGUMENTS:
// Flags - Flags controlling how the voice should be stopped.
// OperationSet - Used to identify this call as part of a deferred batch.
Stop: proc "system" (this: ^IXAudio2SourceVoice, Flags: FLAGS = {}, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2SourceVoice.SubmitSourceBuffer
// DESCRIPTION: Adds a new audio buffer to this voice's input queue.
// ARGUMENTS:
// pBuffer - Pointer to the buffer structure to be queued.
// pBufferWMA - Additional structure used only when submitting XWMA data.
SubmitSourceBuffer: proc "system" (this: ^IXAudio2SourceVoice, pBuffer: ^BUFFER, pBufferWMA: ^BUFFER_WMA = nil) -> HRESULT,
// NAME: IXAudio2SourceVoice.FlushSourceBuffers
// DESCRIPTION: Removes all pending audio buffers from this voice's queue.
FlushSourceBuffers: proc "system" (this: ^IXAudio2SourceVoice) -> HRESULT,
// NAME: IXAudio2SourceVoice.Discontinuity
// DESCRIPTION: Notifies the voice of an intentional break in the stream of audio buffers (e.g. the end of a sound), to prevent XAudio2 from interpreting an empty buffer queue as a glitch.
Discontinuity: proc "system" (this: ^IXAudio2SourceVoice) -> HRESULT,
// NAME: IXAudio2SourceVoice.ExitLoop
// DESCRIPTION: Breaks out of the current loop when its end is reached.
// ARGUMENTS:
// OperationSet - Used to identify this call as part of a deferred batch.
ExitLoop: proc "system" (this: ^IXAudio2SourceVoice, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2SourceVoice.GetState
// DESCRIPTION: Returns the number of buffers currently queued on this voice, the pContext value associated with the currently processing buffer (if any), and other voice state information.
// ARGUMENTS:
// pVoiceState - Returns the state information.
// Flags - Flags controlling what voice state is returned.
GetState: proc "system" (this: ^IXAudio2SourceVoice, pVoiceState: ^VOICE_STATE, Flags: FLAGS = {}),
// NAME: IXAudio2SourceVoice.SetFrequencyRatio
// DESCRIPTION: Sets this voice's frequency adjustment, i.e. its pitch.
// ARGUMENTS:
// Ratio - Frequency change, expressed as source frequency / target frequency.
// OperationSet - Used to identify this call as part of a deferred batch.
SetFrequencyRatio: proc "system" (this: ^IXAudio2SourceVoice, Ratio: f32, OperationSet: u32 = COMMIT_NOW) -> HRESULT,
// NAME: IXAudio2SourceVoice.GetFrequencyRatio
// DESCRIPTION: Returns this voice's current frequency adjustment ratio.
// ARGUMENTS:
// pRatio - Returns the frequency adjustment.
GetFrequencyRatio: proc "system" (this: ^IXAudio2SourceVoice, pRatio: ^f32),
// NAME: IXAudio2SourceVoice.SetSourceSampleRate
// DESCRIPTION: Reconfigures this voice to treat its source data as being at a different sample rate than the original one specified in CreateSourceVoice's pSourceFormat argument.
// ARGUMENTS:
// UINT32 - The intended sample rate of further submitted source data.
SetSourceSampleRate: proc "system" (this: ^IXAudio2SourceVoice, NewSourceSampleRate: u32) -> HRESULT,
}
/**************************************************************************
*
* IXAudio2SubmixVoice: Submixing voice management interface.
*
**************************************************************************/
IXAudio2SubmixVoice :: struct #raw_union {
#subtype ixaudio2voice: IXAudio2Voice,
using ixaudio2submixvoice_vtable: ^IXAudio2SubmixVoice_VTable,
}
IXAudio2SubmixVoice_VTable :: struct {
using ixaudio2voice_vtable: IXAudio2Voice_VTable,
// There are currently no methods specific to submix voices.
}
/**************************************************************************
*
* IXAudio2MasteringVoice: Mastering voice management interface.
*
**************************************************************************/
IXAudio2MasteringVoice :: struct #raw_union {
#subtype ixaudio2voice: IXAudio2Voice,
using ixaudio2masteringvoice_vtable: ^IXAudio2MasteringVoice_VTable,
}
IXAudio2MasteringVoice_VTable :: struct {
using ixaudio2voice_vtable: IXAudio2Voice_VTable,
// NAME: IXAudio2MasteringVoice.GetChannelMask
// DESCRIPTION: Returns the channel mask for this voice
// ARGUMENTS:
// pChannelMask - returns the channel mask for this voice. This corresponds to the dwChannelMask member of WAVEFORMATEXTENSIBLE.
GetChannelMask: proc "system" (this: ^IXAudio2MasteringVoice, pChannelmask: ^win.DWORD) -> HRESULT,
}
/**************************************************************************
*
* IXAudio2EngineCallback: Client notification interface for engine events.
*
* REMARKS: Contains methods to notify the client when certain events happen in the XAudio2 engine. This interface should be implemented by the client.
* XAudio2 will call these methods via the interface pointer provided by the client when it calls IXAudio2.RegisterForCallbacks.
*
**************************************************************************/
IXAudio2EngineCallback :: struct {
using ixaudio2enginecallback_vtable: ^IXAudio2EngineCallback_VTable,
}
IXAudio2EngineCallback_VTable :: struct {
// Called by XAudio2 just before an audio processing pass begins.
OnProcessingPassStart: proc "system" (this: ^IXAudio2EngineCallback),
// Called just after an audio processing pass ends.
OnProcessingPassEnd: proc "system" (this: ^IXAudio2EngineCallback),
// Called in the event of a critical system error which requires XAudio2 to be closed down and restarted. The error code is given in Error.
OnCriticalError: proc "system" (this: ^IXAudio2EngineCallback, Error: HRESULT),
}
/**************************************************************************
*
* IXAudio2VoiceCallback: Client notification interface for voice events.
*
* REMARKS: Contains methods to notify the client when certain events happen in an XAudio2 voice. This interface should be implemented by the client.
* XAudio2 will call these methods via an interface pointer provided by the client in the IXAudio2.CreateSourceVoice call.
*
**************************************************************************/
IXAudio2VoiceCallback :: struct {
using ixaudio2voicecallback_vtable: ^IXAudio2VoiceCallback_VTable,
}
IXAudio2VoiceCallback_VTable :: struct {
// Called just before this voice's processing pass begins.
OnVoiceProcessingPassStart: proc "system" (this: ^IXAudio2VoiceCallback, BytesRequired: u32),
// Called just after this voice's processing pass ends.
OnVoiceProcessingPassEnd: proc "system" (this: ^IXAudio2VoiceCallback),
// Called when this voice has just finished playing a buffer stream (as marked with the END_OF_STREAM flag on the last buffer).
OnStreamEnd: proc "system" (this: ^IXAudio2VoiceCallback),
// Called when this voice is about to start processing a new buffer.
OnBufferStart: proc "system" (this: ^IXAudio2VoiceCallback, pBufferContext: rawptr),
// Called when this voice has just finished processing a buffer.
// The buffer can now be reused or destroyed.
OnBufferEnd: proc "system" (this: ^IXAudio2VoiceCallback, pBufferContext: rawptr),
// Called when this voice has just reached the end position of a loop.
OnLoopEnd: proc "system" (this: ^IXAudio2VoiceCallback, pBufferContext: rawptr),
// Called in the event of a critical error during voice processing, such as a failing xAPO or an error from the hardware XMA decoder.
// The voice may have to be destroyed and re-created to recover from the error.
// The callback arguments report which buffer was being processed when the error occurred, and its HRESULT code.
OnVoiceError: proc "system" (this: ^IXAudio2VoiceCallback, pBufferContext: rawptr, Error: HRESULT),
}
/**************************************************************************
*
* XAudio2Create: Top-level function that creates an XAudio2 instance.
*
* ARGUMENTS:
*
* Flags - Flags specifying the XAudio2 object's behavior.
*
* Processor - A PROCESSOR_FLAGS value that specifies the hardware threads (Xbox) or processors (Windows) that XAudio2 will use.
* Note that XAudio2 supports concurrent processing on multiple threads, using any combination of PROCESSOR_FLAGS flags.
* The values are platform-specific; platform-independent code can use USE_DEFAULT_PROCESSOR to use the default on each platform.
*
**************************************************************************/
@(default_calling_convention="system", link_prefix="XAudio2")
foreign xa2 {
Create :: proc(ppXaudio2: ^^IXAudio2, Flags: FLAGS = {}, Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT ---
}
/**************************************************************************
*
* Utility functions used to convert from pitch in semitones and volume in decibels to the frequency and amplitude ratio units used by XAudio2.
*
**************************************************************************/
// Calculate the argument to SetVolume from a decibel value
DecibelsToAmplitudeRatio :: #force_inline proc "contextless" (Decibels: f32) -> f32 {
return math.pow_f32(10.0, Decibels / 20.0)
}
// Recover a volume in decibels from an amplitude factor
AmplitudeRatioToDecibels :: #force_inline proc "contextless" (Volume: f32) -> f32 {
if Volume == 0 {
return min(f32)
}
return 20.0 * math.log10_f32(Volume)
}
// Calculate the argument to SetFrequencyRatio from a semitone value
SemitonesToFrequencyRatio :: #force_inline proc "contextless" (Semitones: f32) -> f32 {
// FrequencyRatio = 2 ^ Octaves
// = 2 ^ (Semitones / 12)
return math.pow_f32(2.0, Semitones / 12.0)
}
// Recover a pitch in semitones from a frequency ratio
FrequencyRatioToSemitones :: #force_inline proc "contextless" (FrequencyRatio: f32) -> f32 {
// Semitones = 12 * log2(FrequencyRatio)
// = 12 * log2(10) * log10(FrequencyRatio)
return 12.0 * math.log2_f32(FrequencyRatio)
}
// Convert from filter cutoff frequencies expressed in Hertz to the radian frequency values used in FILTER_PARAMETERS.Frequency, state-variable filter types only.
// Use CutoffFrequencyToOnePoleCoefficient() for one-pole filter types.
// Note that the highest CutoffFrequency supported is SampleRate/6.
// Higher values of CutoffFrequency will return MAX_FILTER_FREQUENCY.
CutoffFrequencyToRadians :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 {
if u32(CutoffFrequency * 6.0) >= SampleRate {
return MAX_FILTER_FREQUENCY
}
return 2.0 * math.sin_f32(math.PI * CutoffFrequency / f32(SampleRate))
}
// Convert from radian frequencies back to absolute frequencies in Hertz
RadiansToCutoffFrequency :: #force_inline proc "contextless" (Radians: f32, SampleRate: f32) -> f32 {
return SampleRate * math.asin_f32(Radians / 2.0) / math.PI
}
// Convert from filter cutoff frequencies expressed in Hertz to the filter coefficients used with FILTER_PARAMETERS.Frequency,
// LowPassOnePoleFilter and HighPassOnePoleFilter filter types only.
// Use CutoffFrequencyToRadians() for state-variable filter types.
CutoffFrequencyToOnePoleCoefficient :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 {
if u32(CutoffFrequency) >= SampleRate {
return MAX_FILTER_FREQUENCY
}
return 1.0 - math.pow_f32(1.0 - 2.0 * CutoffFrequency / f32(SampleRate), 2.0)
}
//-------------------------------------------------------------------------
// Description: Audio stream categories
//
// Other - All other streams (default)
// ForegroundOnlyMedia - (deprecated for Win10) Music, Streaming audio
// BackgroundCapableMedia - (deprecated for Win10) Video with audio
// Communications - VOIP, chat, phone call
// Alerts - Alarm, Ring tones
// SoundEffects - Sound effects, clicks, dings
// GameEffects - Game sound effects
// GameMedia - Background audio for games
// GameChat - In game player chat
// Speech - Speech recognition
// Media - Music, Streaming audio
// Movie - Video with audio
// FarFieldSpeech - Capture of far field speech
// UniformSpeech - Uniform, device agnostic speech processing
// VoiceTyping - Dictation, typing by voice
//
AUDIO_STREAM_CATEGORY :: enum i32 {
Other = 0,
//ForegroundOnlyMedia = 1,
//BackgroundCapableMedia = 2,
Communications = 3,
Alerts = 4,
SoundEffects = 5,
GameEffects = 6,
GameMedia = 7,
GameChat = 8,
Speech = 9,
Movie = 10,
Media = 11,
FarFieldSpeech = 12,
UniformSpeech = 13,
VoiceTyping = 14,
}
|