1 /* FAudio - XAudio Reimplementation for FNA 2 * 3 * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not 14 * claim that you wrote the original software. If you use this software in a 15 * product, an acknowledgment in the product documentation would be 16 * appreciated but is not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 * 23 * Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com> 24 * 25 */ 26 27 #include "FACT.h" 28 #include "FACT3D.h" 29 #include "FAudio_internal.h" 30 31 /* Internal AudioEngine Types */ 32 33 typedef struct FACTAudioCategory 34 { 35 uint8_t instanceLimit; 36 uint16_t fadeInMS; 37 uint16_t fadeOutMS; 38 uint8_t maxInstanceBehavior; 39 int16_t parentCategory; 40 float volume; 41 uint8_t visibility; 42 43 uint8_t instanceCount; 44 float currentVolume; 45 } FACTAudioCategory; 46 47 typedef struct FACTVariable 48 { 49 uint8_t accessibility; 50 float initialValue; 51 float minValue; 52 float maxValue; 53 } FACTVariable; 54 55 typedef struct FACTRPCPoint 56 { 57 float x; 58 float y; 59 uint8_t type; 60 } FACTRPCPoint; 61 62 typedef enum FACTRPCParameter 63 { 64 RPC_PARAMETER_VOLUME, 65 RPC_PARAMETER_PITCH, 66 RPC_PARAMETER_REVERBSEND, 67 RPC_PARAMETER_FILTERFREQUENCY, 68 RPC_PARAMETER_FILTERQFACTOR, 69 RPC_PARAMETER_COUNT /* If >=, DSP Parameter! */ 70 } FACTRPCParameter; 71 72 typedef struct FACTRPC 73 { 74 uint16_t variable; 75 uint8_t pointCount; 76 uint16_t parameter; 77 FACTRPCPoint *points; 78 } FACTRPC; 79 80 typedef struct FACTDSPParameter 81 { 82 uint8_t type; 83 float value; 84 float minVal; 85 float maxVal; 86 uint16_t unknown; 87 } FACTDSPParameter; 88 89 typedef struct FACTDSPPreset 90 { 91 uint8_t accessibility; 92 uint32_t parameterCount; 93 FACTDSPParameter *parameters; 94 } FACTDSPPreset; 95 96 typedef enum FACTNoticationsFlags 97 { 98 NOTIFY_CUEDESTROY = 0x0001, 99 NOTIFY_SOUNDBANKDESTROY = 0x0002, 100 NOTIFY_WAVEBANKDESTROY = 0x0004, 101 NOTIFY_WAVEDESTROY = 0x0008, 102 NOTIFY_WAVESTOP = 0x0010, 103 } FACTNoticationsFlags; 104 105 /* Internal SoundBank Types */ 106 107 typedef enum 108 { 109 FACTEVENT_STOP = 0, 110 FACTEVENT_PLAYWAVE = 1, 111 FACTEVENT_PLAYWAVETRACKVARIATION = 3, 112 FACTEVENT_PLAYWAVEEFFECTVARIATION = 4, 113 FACTEVENT_PLAYWAVETRACKEFFECTVARIATION = 6, 114 FACTEVENT_PITCH = 7, 115 FACTEVENT_VOLUME = 8, 116 FACTEVENT_MARKER = 9, 117 FACTEVENT_PITCHREPEATING = 16, 118 FACTEVENT_VOLUMEREPEATING = 17, 119 FACTEVENT_MARKERREPEATING = 18 120 } FACTEventType; 121 122 typedef struct FACTEvent 123 { 124 uint16_t type; 125 uint16_t timestamp; 126 uint16_t randomOffset; 127 FAUDIONAMELESS union 128 { 129 /* Play Wave Event */ 130 struct 131 { 132 uint8_t flags; 133 uint8_t loopCount; 134 uint16_t position; 135 uint16_t angle; 136 137 /* Track Variation */ 138 uint8_t isComplex; 139 FAUDIONAMELESS union 140 { 141 struct 142 { 143 uint16_t track; 144 uint8_t wavebank; 145 } simple; 146 struct 147 { 148 uint16_t variation; 149 uint16_t trackCount; 150 uint16_t *tracks; 151 uint8_t *wavebanks; 152 uint8_t *weights; 153 } complex; 154 }; 155 156 /* Effect Variation */ 157 int16_t minPitch; 158 int16_t maxPitch; 159 float minVolume; 160 float maxVolume; 161 float minFrequency; 162 float maxFrequency; 163 float minQFactor; 164 float maxQFactor; 165 uint16_t variationFlags; 166 } wave; 167 /* Set Pitch/Volume Event */ 168 struct 169 { 170 uint8_t settings; 171 uint16_t repeats; 172 uint16_t frequency; 173 FAUDIONAMELESS union 174 { 175 struct 176 { 177 float initialValue; 178 float initialSlope; 179 float slopeDelta; 180 uint16_t duration; 181 } ramp; 182 struct 183 { 184 uint8_t flags; 185 float value1; 186 float value2; 187 } equation; 188 }; 189 } value; 190 /* Stop Event */ 191 struct 192 { 193 uint8_t flags; 194 } stop; 195 /* Marker Event */ 196 struct 197 { 198 uint32_t marker; 199 uint16_t repeats; 200 uint16_t frequency; 201 } marker; 202 }; 203 } FACTEvent; 204 205 typedef struct FACTTrack 206 { 207 uint32_t code; 208 209 float volume; 210 uint8_t filter; 211 uint8_t qfactor; 212 uint16_t frequency; 213 214 uint8_t rpcCodeCount; 215 uint32_t *rpcCodes; 216 217 uint8_t eventCount; 218 FACTEvent *events; 219 } FACTTrack; 220 221 typedef struct FACTSound 222 { 223 uint8_t flags; 224 uint16_t category; 225 float volume; 226 int16_t pitch; 227 uint8_t priority; 228 229 uint8_t trackCount; 230 uint8_t rpcCodeCount; 231 uint8_t dspCodeCount; 232 233 FACTTrack *tracks; 234 uint32_t *rpcCodes; 235 uint32_t *dspCodes; 236 } FACTSound; 237 238 typedef struct FACTCueData 239 { 240 uint8_t flags; 241 uint32_t sbCode; 242 uint32_t transitionOffset; 243 uint8_t instanceLimit; 244 uint16_t fadeInMS; 245 uint16_t fadeOutMS; 246 uint8_t maxInstanceBehavior; 247 uint8_t instanceCount; 248 } FACTCueData; 249 250 typedef struct FACTVariation 251 { 252 FAUDIONAMELESS union 253 { 254 struct 255 { 256 uint16_t track; 257 uint8_t wavebank; 258 } simple; 259 uint32_t soundCode; 260 }; 261 float minWeight; 262 float maxWeight; 263 uint32_t linger; 264 } FACTVariation; 265 266 typedef struct FACTVariationTable 267 { 268 uint8_t flags; 269 int16_t variable; 270 uint8_t isComplex; 271 272 uint16_t entryCount; 273 FACTVariation *entries; 274 } FACTVariationTable; 275 276 typedef struct FACTTransition 277 { 278 int32_t soundCode; 279 uint32_t srcMarkerMin; 280 uint32_t srcMarkerMax; 281 uint32_t dstMarkerMin; 282 uint32_t dstMarkerMax; 283 uint16_t fadeIn; 284 uint16_t fadeOut; 285 uint16_t flags; 286 } FACTTransition; 287 288 typedef struct FACTTransitionTable 289 { 290 uint32_t entryCount; 291 FACTTransition *entries; 292 } FACTTransitionTable; 293 294 /* Internal WaveBank Types */ 295 296 typedef struct FACTSeekTable 297 { 298 uint32_t entryCount; 299 uint32_t *entries; 300 } FACTSeekTable; 301 302 /* Internal Cue Types */ 303 304 typedef struct FACTInstanceRPCData 305 { 306 float rpcVolume; 307 float rpcPitch; 308 float rpcReverbSend; 309 float rpcFilterFreq; 310 float rpcFilterQFactor; 311 } FACTInstanceRPCData; 312 313 typedef struct FACTEventInstance 314 { 315 uint32_t timestamp; 316 uint16_t loopCount; 317 uint8_t finished; 318 FAUDIONAMELESS union 319 { 320 float value; 321 uint32_t valuei; 322 }; 323 } FACTEventInstance; 324 325 typedef struct FACTTrackInstance 326 { 327 /* Tracks which events have fired */ 328 FACTEventInstance *events; 329 330 /* RPC instance data */ 331 FACTInstanceRPCData rpcData; 332 333 /* SetPitch/SetVolume data */ 334 float evtPitch; 335 float evtVolume; 336 337 /* Wave playback */ 338 struct 339 { 340 FACTWave *wave; 341 float baseVolume; 342 int16_t basePitch; 343 float baseQFactor; 344 float baseFrequency; 345 } activeWave, upcomingWave; 346 FACTEvent *waveEvt; 347 FACTEventInstance *waveEvtInst; 348 } FACTTrackInstance; 349 350 typedef struct FACTSoundInstance 351 { 352 /* Base Sound reference */ 353 FACTSound *sound; 354 355 /* Per-instance track information */ 356 FACTTrackInstance *tracks; 357 358 /* RPC instance data */ 359 FACTInstanceRPCData rpcData; 360 361 /* Fade data */ 362 uint32_t fadeStart; 363 uint16_t fadeTarget; 364 uint8_t fadeType; /* In (1), Out (2), Release RPC (3) */ 365 366 /* Engine references */ 367 FACTCue *parentCue; 368 } FACTSoundInstance; 369 370 /* Internal Wave Types */ 371 372 typedef struct FACTWaveCallback 373 { 374 FAudioVoiceCallback callback; 375 FACTWave *wave; 376 } FACTWaveCallback; 377 378 /* Public XACT Types */ 379 380 struct FACTAudioEngine 381 { 382 uint32_t refcount; 383 FACTNotificationCallback notificationCallback; 384 FACTReadFileCallback pReadFile; 385 FACTGetOverlappedResultCallback pGetOverlappedResult; 386 387 uint16_t categoryCount; 388 uint16_t variableCount; 389 uint16_t rpcCount; 390 uint16_t dspPresetCount; 391 uint16_t dspParameterCount; 392 393 char **categoryNames; 394 char **variableNames; 395 uint32_t *rpcCodes; 396 uint32_t *dspPresetCodes; 397 398 FACTAudioCategory *categories; 399 FACTVariable *variables; 400 FACTRPC *rpcs; 401 FACTDSPPreset *dspPresets; 402 403 /* Engine references */ 404 LinkedList *sbList; 405 LinkedList *wbList; 406 FAudioMutex sbLock; 407 FAudioMutex wbLock; 408 float *globalVariableValues; 409 410 /* FAudio references */ 411 FAudio *audio; 412 FAudioMasteringVoice *master; 413 FAudioSubmixVoice *reverbVoice; 414 415 /* Engine thread */ 416 FAudioThread apiThread; 417 FAudioMutex apiLock; 418 uint8_t initialized; 419 420 /* Allocator callbacks */ 421 FAudioMallocFunc pMalloc; 422 FAudioFreeFunc pFree; 423 FAudioReallocFunc pRealloc; 424 425 /* Peristent Notifications */ 426 FACTNoticationsFlags notifications; 427 void *cue_context; 428 void *sb_context; 429 void *wb_context; 430 void *wave_context; 431 }; 432 433 struct FACTSoundBank 434 { 435 /* Engine references */ 436 FACTAudioEngine *parentEngine; 437 FACTCue *cueList; 438 uint8_t notifyOnDestroy; 439 void *usercontext; 440 441 /* Array sizes */ 442 uint16_t cueCount; 443 uint8_t wavebankCount; 444 uint16_t soundCount; 445 uint16_t variationCount; 446 uint16_t transitionCount; 447 448 /* Strings, strings everywhere! */ 449 char **wavebankNames; 450 char **cueNames; 451 452 /* Actual SoundBank information */ 453 char *name; 454 FACTCueData *cues; 455 FACTSound *sounds; 456 uint32_t *soundCodes; 457 FACTVariationTable *variations; 458 uint32_t *variationCodes; 459 FACTTransitionTable *transitions; 460 uint32_t *transitionCodes; 461 }; 462 463 struct FACTWaveBank 464 { 465 /* Engine references */ 466 FACTAudioEngine *parentEngine; 467 LinkedList *waveList; 468 FAudioMutex waveLock; 469 uint8_t notifyOnDestroy; 470 void *usercontext; 471 472 /* Actual WaveBank information */ 473 char *name; 474 uint32_t entryCount; 475 FACTWaveBankEntry *entries; 476 uint32_t *entryRefs; 477 FACTSeekTable *seekTables; 478 479 /* I/O information */ 480 uint32_t packetSize; 481 uint16_t streaming; 482 uint8_t *packetBuffer; 483 uint32_t packetBufferLen; 484 void* io; 485 }; 486 487 struct FACTWave 488 { 489 /* Engine references */ 490 FACTWaveBank *parentBank; 491 FACTCue *parentCue; 492 uint16_t index; 493 uint8_t notifyOnDestroy; 494 void *usercontext; 495 496 /* Playback */ 497 uint32_t state; 498 float volume; 499 int16_t pitch; 500 uint8_t loopCount; 501 502 /* Stream data */ 503 uint32_t streamSize; 504 uint32_t streamOffset; 505 uint8_t *streamCache; 506 507 /* FAudio references */ 508 uint16_t srcChannels; 509 FAudioSourceVoice *voice; 510 FACTWaveCallback callback; 511 }; 512 513 struct FACTCue 514 { 515 /* Engine references */ 516 FACTSoundBank *parentBank; 517 FACTCue *next; 518 uint8_t managed; 519 uint16_t index; 520 uint8_t notifyOnDestroy; 521 void *usercontext; 522 523 /* Sound data */ 524 FACTCueData *data; 525 FAUDIONAMELESS union 526 { 527 FACTVariationTable *variation; 528 529 /* This is only used in scenarios where there is only one 530 * Sound; XACT does not generate variation tables for 531 * Cues with only one Sound. 532 */ 533 FACTSound *sound; 534 }; 535 536 /* Instance data */ 537 float *variableValues; 538 float interactive; 539 540 /* Playback */ 541 uint32_t state; 542 FACTWave *simpleWave; 543 FACTSoundInstance *playingSound; 544 FACTVariation *playingVariation; 545 uint32_t maxRpcReleaseTime; 546 547 /* 3D Data */ 548 uint8_t active3D; 549 uint32_t srcChannels; 550 uint32_t dstChannels; 551 float matrixCoefficients[2 * 8]; /* Stereo input, 7.1 output */ 552 553 /* Timer */ 554 uint32_t start; 555 uint32_t elapsed; 556 }; 557 558 /* Internal functions */ 559 560 void FACT_INTERNAL_GetNextWave( 561 FACTCue *cue, 562 FACTSound *sound, 563 FACTTrack *track, 564 FACTTrackInstance *trackInst, 565 FACTEvent *evt, 566 FACTEventInstance *evtInst 567 ); 568 uint8_t FACT_INTERNAL_CreateSound(FACTCue *cue, uint16_t fadeInMS); 569 void FACT_INTERNAL_DestroySound(FACTSoundInstance *sound); 570 void FACT_INTERNAL_BeginFadeOut(FACTSoundInstance *sound, uint16_t fadeOutMS); 571 void FACT_INTERNAL_BeginReleaseRPC(FACTSoundInstance *sound, uint16_t releaseMS); 572 573 /* RPC Helper Functions */ 574 575 FACTRPC* FACT_INTERNAL_GetRPC(FACTAudioEngine *engine, uint32_t code); 576 577 /* FACT Thread */ 578 579 int32_t FAUDIOCALL FACT_INTERNAL_APIThread(void* enginePtr); 580 581 /* FAudio callbacks */ 582 583 void FACT_INTERNAL_OnBufferEnd(FAudioVoiceCallback *callback, void* pContext); 584 void FACT_INTERNAL_OnStreamEnd(FAudioVoiceCallback *callback); 585 586 /* FAudioIOStream functions */ 587 588 int32_t FACTCALL FACT_INTERNAL_DefaultReadFile( 589 void *hFile, 590 void *buffer, 591 uint32_t nNumberOfBytesToRead, 592 uint32_t *lpNumberOfBytesRead, 593 FACTOverlapped *lpOverlapped 594 ); 595 596 int32_t FACTCALL FACT_INTERNAL_DefaultGetOverlappedResult( 597 void *hFile, 598 FACTOverlapped *lpOverlapped, 599 uint32_t *lpNumberOfBytesTransferred, 600 int32_t bWait 601 ); 602 603 /* Parsing functions */ 604 605 uint32_t FACT_INTERNAL_ParseAudioEngine( 606 FACTAudioEngine *pEngine, 607 const FACTRuntimeParameters *pParams 608 ); 609 uint32_t FACT_INTERNAL_ParseSoundBank( 610 FACTAudioEngine *pEngine, 611 const void *pvBuffer, 612 uint32_t dwSize, 613 FACTSoundBank **ppSoundBank 614 ); 615 uint32_t FACT_INTERNAL_ParseWaveBank( 616 FACTAudioEngine *pEngine, 617 void* io, 618 uint32_t offset, 619 uint32_t packetSize, 620 FACTReadFileCallback pRead, 621 FACTGetOverlappedResultCallback pOverlap, 622 uint16_t isStreaming, 623 FACTWaveBank **ppWaveBank 624 ); 625 626 /* vim: set noexpandtab shiftwidth=8 tabstop=8: */ 627