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 /* FAudio_operationset.c originally written by Tyler Glaiel */
28
29 #include "FAudio_internal.h"
30
31 /* Core OperationSet Types */
32
33 typedef enum FAudio_OPERATIONSET_Type
34 {
35 FAUDIOOP_ENABLEEFFECT,
36 FAUDIOOP_DISABLEEFFECT,
37 FAUDIOOP_SETEFFECTPARAMETERS,
38 FAUDIOOP_SETFILTERPARAMETERS,
39 FAUDIOOP_SETOUTPUTFILTERPARAMETERS,
40 FAUDIOOP_SETVOLUME,
41 FAUDIOOP_SETCHANNELVOLUMES,
42 FAUDIOOP_SETOUTPUTMATRIX,
43 FAUDIOOP_START,
44 FAUDIOOP_STOP,
45 FAUDIOOP_EXITLOOP,
46 FAUDIOOP_SETFREQUENCYRATIO
47 } FAudio_OPERATIONSET_Type;
48
49 struct FAudio_OPERATIONSET_Operation
50 {
51 FAudio_OPERATIONSET_Type Type;
52 uint32_t OperationSet;
53 FAudioVoice *Voice;
54
55 union
56 {
57 struct
58 {
59 uint32_t EffectIndex;
60 } EnableEffect;
61 struct
62 {
63 uint32_t EffectIndex;
64 } DisableEffect;
65 struct
66 {
67 uint32_t EffectIndex;
68 void *pParameters;
69 uint32_t ParametersByteSize;
70 } SetEffectParameters;
71 struct
72 {
73 FAudioFilterParameters Parameters;
74 } SetFilterParameters;
75 struct
76 {
77 FAudioVoice *pDestinationVoice;
78 FAudioFilterParameters Parameters;
79 } SetOutputFilterParameters;
80 struct
81 {
82 float Volume;
83 } SetVolume;
84 struct
85 {
86 uint32_t Channels;
87 float *pVolumes;
88 } SetChannelVolumes;
89 struct
90 {
91 FAudioVoice *pDestinationVoice;
92 uint32_t SourceChannels;
93 uint32_t DestinationChannels;
94 float *pLevelMatrix;
95 } SetOutputMatrix;
96 struct
97 {
98 uint32_t Flags;
99 } Start;
100 struct
101 {
102 uint32_t Flags;
103 } Stop;
104 /* No special data for ExitLoop
105 struct
106 {
107 } ExitLoop;
108 */
109 struct
110 {
111 float Ratio;
112 } SetFrequencyRatio;
113 } Data;
114
115 FAudio_OPERATIONSET_Operation *next;
116 };
117
118 /* Used by both Commit and Clear routines */
119
DeleteOperation(FAudio_OPERATIONSET_Operation * op,FAudioFreeFunc pFree)120 static inline void DeleteOperation(
121 FAudio_OPERATIONSET_Operation *op,
122 FAudioFreeFunc pFree
123 ) {
124 if (op->Type == FAUDIOOP_SETEFFECTPARAMETERS)
125 {
126 pFree(op->Data.SetEffectParameters.pParameters);
127 }
128 else if (op->Type == FAUDIOOP_SETCHANNELVOLUMES)
129 {
130 pFree(op->Data.SetChannelVolumes.pVolumes);
131 }
132 else if (op->Type == FAUDIOOP_SETOUTPUTMATRIX)
133 {
134 pFree(op->Data.SetOutputMatrix.pLevelMatrix);
135 }
136 pFree(op);
137 }
138
139 /* OperationSet Execution */
140
ExecuteOperation(FAudio_OPERATIONSET_Operation * op)141 static inline void ExecuteOperation(FAudio_OPERATIONSET_Operation *op)
142 {
143 switch (op->Type)
144 {
145 case FAUDIOOP_ENABLEEFFECT:
146 FAudioVoice_EnableEffect(
147 op->Voice,
148 op->Data.EnableEffect.EffectIndex,
149 FAUDIO_COMMIT_NOW
150 );
151 break;
152
153 case FAUDIOOP_DISABLEEFFECT:
154 FAudioVoice_DisableEffect(
155 op->Voice,
156 op->Data.DisableEffect.EffectIndex,
157 FAUDIO_COMMIT_NOW
158 );
159 break;
160
161 case FAUDIOOP_SETEFFECTPARAMETERS:
162 FAudioVoice_SetEffectParameters(
163 op->Voice,
164 op->Data.SetEffectParameters.EffectIndex,
165 op->Data.SetEffectParameters.pParameters,
166 op->Data.SetEffectParameters.ParametersByteSize,
167 FAUDIO_COMMIT_NOW
168 );
169 break;
170
171 case FAUDIOOP_SETFILTERPARAMETERS:
172 FAudioVoice_SetFilterParameters(
173 op->Voice,
174 &op->Data.SetFilterParameters.Parameters,
175 FAUDIO_COMMIT_NOW
176 );
177 break;
178
179 case FAUDIOOP_SETOUTPUTFILTERPARAMETERS:
180 FAudioVoice_SetOutputFilterParameters(
181 op->Voice,
182 op->Data.SetOutputFilterParameters.pDestinationVoice,
183 &op->Data.SetOutputFilterParameters.Parameters,
184 FAUDIO_COMMIT_NOW
185 );
186 break;
187
188 case FAUDIOOP_SETVOLUME:
189 FAudioVoice_SetVolume(
190 op->Voice,
191 op->Data.SetVolume.Volume,
192 FAUDIO_COMMIT_NOW
193 );
194 break;
195
196 case FAUDIOOP_SETCHANNELVOLUMES:
197 FAudioVoice_SetChannelVolumes(
198 op->Voice,
199 op->Data.SetChannelVolumes.Channels,
200 op->Data.SetChannelVolumes.pVolumes,
201 FAUDIO_COMMIT_NOW
202 );
203 break;
204
205 case FAUDIOOP_SETOUTPUTMATRIX:
206 FAudioVoice_SetOutputMatrix(
207 op->Voice,
208 op->Data.SetOutputMatrix.pDestinationVoice,
209 op->Data.SetOutputMatrix.SourceChannels,
210 op->Data.SetOutputMatrix.DestinationChannels,
211 op->Data.SetOutputMatrix.pLevelMatrix,
212 FAUDIO_COMMIT_NOW
213 );
214 break;
215
216 case FAUDIOOP_START:
217 FAudioSourceVoice_Start(
218 op->Voice,
219 op->Data.Start.Flags,
220 FAUDIO_COMMIT_NOW
221 );
222 break;
223
224 case FAUDIOOP_STOP:
225 FAudioSourceVoice_Stop(
226 op->Voice,
227 op->Data.Stop.Flags,
228 FAUDIO_COMMIT_NOW
229 );
230 break;
231
232 case FAUDIOOP_EXITLOOP:
233 FAudioSourceVoice_ExitLoop(
234 op->Voice,
235 FAUDIO_COMMIT_NOW
236 );
237 break;
238
239 case FAUDIOOP_SETFREQUENCYRATIO:
240 FAudioSourceVoice_SetFrequencyRatio(
241 op->Voice,
242 op->Data.SetFrequencyRatio.Ratio,
243 FAUDIO_COMMIT_NOW
244 );
245 break;
246
247 default:
248 FAudio_assert(0 && "Unrecognized operation type!");
249 break;
250 }
251 }
252
FAudio_OPERATIONSET_CommitAll(FAudio * audio)253 void FAudio_OPERATIONSET_CommitAll(FAudio *audio)
254 {
255 FAudio_OPERATIONSET_Operation *op, *next, **committed_end;
256
257 FAudio_PlatformLockMutex(audio->operationLock);
258 LOG_MUTEX_LOCK(audio, audio->operationLock)
259
260 if (audio->queuedOperations == NULL)
261 {
262 FAudio_PlatformUnlockMutex(audio->operationLock);
263 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
264 return;
265 }
266
267 committed_end = &audio->committedOperations;
268 while (*committed_end)
269 {
270 committed_end = &((*committed_end)->next);
271 }
272
273 op = audio->queuedOperations;
274 do
275 {
276 next = op->next;
277
278 *committed_end = op;
279 op->next = NULL;
280 committed_end = &op->next;
281
282 op = next;
283 } while (op != NULL);
284 audio->queuedOperations = NULL;
285
286 FAudio_PlatformUnlockMutex(audio->operationLock);
287 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
288 }
289
FAudio_OPERATIONSET_Commit(FAudio * audio,uint32_t OperationSet)290 void FAudio_OPERATIONSET_Commit(FAudio *audio, uint32_t OperationSet)
291 {
292 FAudio_OPERATIONSET_Operation *op, *next, *prev, **committed_end;
293
294 FAudio_PlatformLockMutex(audio->operationLock);
295 LOG_MUTEX_LOCK(audio, audio->operationLock)
296
297 if (audio->queuedOperations == NULL)
298 {
299 FAudio_PlatformUnlockMutex(audio->operationLock);
300 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
301 return;
302 }
303
304 committed_end = &audio->committedOperations;
305 while (*committed_end)
306 {
307 committed_end = &((*committed_end)->next);
308 }
309
310 op = audio->queuedOperations;
311 prev = NULL;
312 do
313 {
314 next = op->next;
315 if (op->OperationSet == OperationSet)
316 {
317 if (prev == NULL) /* Start of linked list */
318 {
319 audio->queuedOperations = next;
320 }
321 else
322 {
323 prev->next = next;
324 }
325
326 *committed_end = op;
327 op->next = NULL;
328 committed_end = &op->next;
329 }
330 else
331 {
332 prev = op;
333 }
334 op = next;
335 } while (op != NULL);
336
337 FAudio_PlatformUnlockMutex(audio->operationLock);
338 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
339 }
340
FAudio_OPERATIONSET_Execute(FAudio * audio)341 void FAudio_OPERATIONSET_Execute(FAudio *audio)
342 {
343 FAudio_OPERATIONSET_Operation *op, *next;
344
345 FAudio_PlatformLockMutex(audio->operationLock);
346 LOG_MUTEX_LOCK(audio, audio->operationLock)
347
348 op = audio->committedOperations;
349 while (op != NULL)
350 {
351 next = op->next;
352 ExecuteOperation(op);
353 DeleteOperation(op, audio->pFree);
354 op = next;
355 }
356 audio->committedOperations = NULL;
357
358 FAudio_PlatformUnlockMutex(audio->operationLock);
359 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
360 }
361
362 /* OperationSet Compilation */
363
QueueOperation(FAudioVoice * voice,FAudio_OPERATIONSET_Type type,uint32_t operationSet)364 static inline FAudio_OPERATIONSET_Operation* QueueOperation(
365 FAudioVoice *voice,
366 FAudio_OPERATIONSET_Type type,
367 uint32_t operationSet
368 ) {
369 FAudio_OPERATIONSET_Operation *latest;
370 FAudio_OPERATIONSET_Operation *newop = voice->audio->pMalloc(
371 sizeof(FAudio_OPERATIONSET_Operation)
372 );
373
374 newop->Type = type;
375 newop->Voice = voice;
376 newop->OperationSet = operationSet;
377 newop->next = NULL;
378
379 if (voice->audio->queuedOperations == NULL)
380 {
381 voice->audio->queuedOperations = newop;
382 }
383 else
384 {
385 latest = voice->audio->queuedOperations;
386 while (latest->next != NULL)
387 {
388 latest = latest->next;
389 }
390 latest->next = newop;
391 }
392
393 return newop;
394 }
395
FAudio_OPERATIONSET_QueueEnableEffect(FAudioVoice * voice,uint32_t EffectIndex,uint32_t OperationSet)396 void FAudio_OPERATIONSET_QueueEnableEffect(
397 FAudioVoice *voice,
398 uint32_t EffectIndex,
399 uint32_t OperationSet
400 ) {
401 FAudio_OPERATIONSET_Operation *op;
402
403 FAudio_PlatformLockMutex(voice->audio->operationLock);
404 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
405
406 op = QueueOperation(
407 voice,
408 FAUDIOOP_ENABLEEFFECT,
409 OperationSet
410 );
411
412 op->Data.EnableEffect.EffectIndex = EffectIndex;
413
414 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
415 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
416 }
417
FAudio_OPERATIONSET_QueueDisableEffect(FAudioVoice * voice,uint32_t EffectIndex,uint32_t OperationSet)418 void FAudio_OPERATIONSET_QueueDisableEffect(
419 FAudioVoice *voice,
420 uint32_t EffectIndex,
421 uint32_t OperationSet
422 ) {
423 FAudio_OPERATIONSET_Operation *op;
424
425 FAudio_PlatformLockMutex(voice->audio->operationLock);
426 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
427
428 op = QueueOperation(
429 voice,
430 FAUDIOOP_DISABLEEFFECT,
431 OperationSet
432 );
433
434 op->Data.DisableEffect.EffectIndex = EffectIndex;
435
436 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
437 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
438 }
439
FAudio_OPERATIONSET_QueueSetEffectParameters(FAudioVoice * voice,uint32_t EffectIndex,const void * pParameters,uint32_t ParametersByteSize,uint32_t OperationSet)440 void FAudio_OPERATIONSET_QueueSetEffectParameters(
441 FAudioVoice *voice,
442 uint32_t EffectIndex,
443 const void *pParameters,
444 uint32_t ParametersByteSize,
445 uint32_t OperationSet
446 ) {
447 FAudio_OPERATIONSET_Operation *op;
448
449 FAudio_PlatformLockMutex(voice->audio->operationLock);
450 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
451
452 op = QueueOperation(
453 voice,
454 FAUDIOOP_SETEFFECTPARAMETERS,
455 OperationSet
456 );
457
458 op->Data.SetEffectParameters.EffectIndex = EffectIndex;
459 op->Data.SetEffectParameters.pParameters = voice->audio->pMalloc(
460 ParametersByteSize
461 );
462 FAudio_memcpy(
463 op->Data.SetEffectParameters.pParameters,
464 pParameters,
465 ParametersByteSize
466 );
467 op->Data.SetEffectParameters.ParametersByteSize = ParametersByteSize;
468
469 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
470 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
471 }
472
FAudio_OPERATIONSET_QueueSetFilterParameters(FAudioVoice * voice,const FAudioFilterParameters * pParameters,uint32_t OperationSet)473 void FAudio_OPERATIONSET_QueueSetFilterParameters(
474 FAudioVoice *voice,
475 const FAudioFilterParameters *pParameters,
476 uint32_t OperationSet
477 ) {
478 FAudio_OPERATIONSET_Operation *op;
479
480 FAudio_PlatformLockMutex(voice->audio->operationLock);
481 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
482
483 op = QueueOperation(
484 voice,
485 FAUDIOOP_SETFILTERPARAMETERS,
486 OperationSet
487 );
488
489 FAudio_memcpy(
490 &op->Data.SetFilterParameters.Parameters,
491 pParameters,
492 sizeof(FAudioFilterParameters)
493 );
494
495 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
496 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
497 }
498
FAudio_OPERATIONSET_QueueSetOutputFilterParameters(FAudioVoice * voice,FAudioVoice * pDestinationVoice,const FAudioFilterParameters * pParameters,uint32_t OperationSet)499 void FAudio_OPERATIONSET_QueueSetOutputFilterParameters(
500 FAudioVoice *voice,
501 FAudioVoice *pDestinationVoice,
502 const FAudioFilterParameters *pParameters,
503 uint32_t OperationSet
504 ) {
505 FAudio_OPERATIONSET_Operation *op;
506
507 FAudio_PlatformLockMutex(voice->audio->operationLock);
508 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
509
510 op = QueueOperation(
511 voice,
512 FAUDIOOP_SETOUTPUTFILTERPARAMETERS,
513 OperationSet
514 );
515
516 op->Data.SetOutputFilterParameters.pDestinationVoice = pDestinationVoice;
517 FAudio_memcpy(
518 &op->Data.SetOutputFilterParameters.Parameters,
519 pParameters,
520 sizeof(FAudioFilterParameters)
521 );
522
523 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
524 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
525 }
526
FAudio_OPERATIONSET_QueueSetVolume(FAudioVoice * voice,float Volume,uint32_t OperationSet)527 void FAudio_OPERATIONSET_QueueSetVolume(
528 FAudioVoice *voice,
529 float Volume,
530 uint32_t OperationSet
531 ) {
532 FAudio_OPERATIONSET_Operation *op;
533
534 FAudio_PlatformLockMutex(voice->audio->operationLock);
535 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
536
537 op = QueueOperation(
538 voice,
539 FAUDIOOP_SETVOLUME,
540 OperationSet
541 );
542
543 op->Data.SetVolume.Volume = Volume;
544
545 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
546 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
547 }
548
FAudio_OPERATIONSET_QueueSetChannelVolumes(FAudioVoice * voice,uint32_t Channels,const float * pVolumes,uint32_t OperationSet)549 void FAudio_OPERATIONSET_QueueSetChannelVolumes(
550 FAudioVoice *voice,
551 uint32_t Channels,
552 const float *pVolumes,
553 uint32_t OperationSet
554 ) {
555 FAudio_OPERATIONSET_Operation *op;
556
557 FAudio_PlatformLockMutex(voice->audio->operationLock);
558 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
559
560 op = QueueOperation(
561 voice,
562 FAUDIOOP_SETCHANNELVOLUMES,
563 OperationSet
564 );
565
566 op->Data.SetChannelVolumes.Channels = Channels;
567 op->Data.SetChannelVolumes.pVolumes = voice->audio->pMalloc(
568 sizeof(float) * Channels
569 );
570 FAudio_memcpy(
571 op->Data.SetChannelVolumes.pVolumes,
572 pVolumes,
573 sizeof(float) * Channels
574 );
575
576 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
577 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
578 }
579
FAudio_OPERATIONSET_QueueSetOutputMatrix(FAudioVoice * voice,FAudioVoice * pDestinationVoice,uint32_t SourceChannels,uint32_t DestinationChannels,const float * pLevelMatrix,uint32_t OperationSet)580 void FAudio_OPERATIONSET_QueueSetOutputMatrix(
581 FAudioVoice *voice,
582 FAudioVoice *pDestinationVoice,
583 uint32_t SourceChannels,
584 uint32_t DestinationChannels,
585 const float *pLevelMatrix,
586 uint32_t OperationSet
587 ) {
588 FAudio_OPERATIONSET_Operation *op;
589
590 FAudio_PlatformLockMutex(voice->audio->operationLock);
591 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
592
593 op = QueueOperation(
594 voice,
595 FAUDIOOP_SETOUTPUTMATRIX,
596 OperationSet
597 );
598
599 op->Data.SetOutputMatrix.pDestinationVoice = pDestinationVoice;
600 op->Data.SetOutputMatrix.SourceChannels = SourceChannels;
601 op->Data.SetOutputMatrix.DestinationChannels = DestinationChannels;
602 op->Data.SetOutputMatrix.pLevelMatrix = voice->audio->pMalloc(
603 sizeof(float) * SourceChannels * DestinationChannels
604 );
605 FAudio_memcpy(
606 op->Data.SetOutputMatrix.pLevelMatrix,
607 pLevelMatrix,
608 sizeof(float) * SourceChannels * DestinationChannels
609 );
610
611 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
612 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
613 }
614
FAudio_OPERATIONSET_QueueStart(FAudioSourceVoice * voice,uint32_t Flags,uint32_t OperationSet)615 void FAudio_OPERATIONSET_QueueStart(
616 FAudioSourceVoice *voice,
617 uint32_t Flags,
618 uint32_t OperationSet
619 ) {
620 FAudio_OPERATIONSET_Operation *op;
621
622 FAudio_PlatformLockMutex(voice->audio->operationLock);
623 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
624
625 op = QueueOperation(
626 voice,
627 FAUDIOOP_START,
628 OperationSet
629 );
630
631 op->Data.Start.Flags = Flags;
632
633 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
634 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
635 }
636
FAudio_OPERATIONSET_QueueStop(FAudioSourceVoice * voice,uint32_t Flags,uint32_t OperationSet)637 void FAudio_OPERATIONSET_QueueStop(
638 FAudioSourceVoice *voice,
639 uint32_t Flags,
640 uint32_t OperationSet
641 ) {
642 FAudio_OPERATIONSET_Operation *op;
643
644 FAudio_PlatformLockMutex(voice->audio->operationLock);
645 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
646
647 op = QueueOperation(
648 voice,
649 FAUDIOOP_STOP,
650 OperationSet
651 );
652
653 op->Data.Stop.Flags = Flags;
654
655 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
656 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
657 }
658
FAudio_OPERATIONSET_QueueExitLoop(FAudioSourceVoice * voice,uint32_t OperationSet)659 void FAudio_OPERATIONSET_QueueExitLoop(
660 FAudioSourceVoice *voice,
661 uint32_t OperationSet
662 ) {
663 FAudio_PlatformLockMutex(voice->audio->operationLock);
664 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
665
666 QueueOperation(
667 voice,
668 FAUDIOOP_EXITLOOP,
669 OperationSet
670 );
671
672 /* No special data for ExitLoop */
673
674 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
675 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
676 }
677
FAudio_OPERATIONSET_QueueSetFrequencyRatio(FAudioSourceVoice * voice,float Ratio,uint32_t OperationSet)678 void FAudio_OPERATIONSET_QueueSetFrequencyRatio(
679 FAudioSourceVoice *voice,
680 float Ratio,
681 uint32_t OperationSet
682 ) {
683 FAudio_OPERATIONSET_Operation *op;
684
685 FAudio_PlatformLockMutex(voice->audio->operationLock);
686 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
687
688 op = QueueOperation(
689 voice,
690 FAUDIOOP_SETFREQUENCYRATIO,
691 OperationSet
692 );
693
694 op->Data.SetFrequencyRatio.Ratio = Ratio;
695
696 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
697 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
698 }
699
700 /* Called when releasing the engine */
701
FAudio_OPERATIONSET_ClearAll(FAudio * audio)702 void FAudio_OPERATIONSET_ClearAll(FAudio *audio)
703 {
704 FAudio_OPERATIONSET_Operation *current, *next;
705
706 FAudio_PlatformLockMutex(audio->operationLock);
707 LOG_MUTEX_LOCK(audio, audio->operationLock)
708
709 current = audio->queuedOperations;
710 while (current != NULL)
711 {
712 next = current->next;
713 DeleteOperation(current, audio->pFree);
714 current = next;
715 }
716 audio->queuedOperations = NULL;
717
718 FAudio_PlatformUnlockMutex(audio->operationLock);
719 LOG_MUTEX_UNLOCK(audio, audio->operationLock)
720 }
721
722 /* Called when releasing a voice */
723
RemoveFromList(FAudioVoice * voice,FAudio_OPERATIONSET_Operation ** list)724 static inline void RemoveFromList(
725 FAudioVoice *voice,
726 FAudio_OPERATIONSET_Operation **list
727 ) {
728 FAudio_OPERATIONSET_Operation *current, *next, *prev;
729
730 current = *list;
731 prev = NULL;
732 while (current != NULL)
733 {
734 const uint8_t baseVoice = (voice == current->Voice);
735 const uint8_t dstVoice = (
736 current->Type == FAUDIOOP_SETOUTPUTFILTERPARAMETERS &&
737 voice == current->Data.SetOutputFilterParameters.pDestinationVoice
738 ) || (
739 current->Type == FAUDIOOP_SETOUTPUTMATRIX &&
740 voice == current->Data.SetOutputMatrix.pDestinationVoice
741 );
742
743 next = current->next;
744 if (baseVoice || dstVoice)
745 {
746 if (prev == NULL) /* Start of linked list */
747 {
748 *list = next;
749 }
750 else
751 {
752 prev->next = next;
753 }
754
755 DeleteOperation(current, voice->audio->pFree);
756 }
757 else
758 {
759 prev = current;
760 }
761 current = next;
762 }
763 }
764
FAudio_OPERATIONSET_ClearAllForVoice(FAudioVoice * voice)765 void FAudio_OPERATIONSET_ClearAllForVoice(FAudioVoice *voice)
766 {
767 FAudio_PlatformLockMutex(voice->audio->operationLock);
768 LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
769
770 RemoveFromList(voice, &voice->audio->queuedOperations);
771 RemoveFromList(voice, &voice->audio->committedOperations);
772
773 FAudio_PlatformUnlockMutex(voice->audio->operationLock);
774 LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
775 }
776
777 /* vim: set noexpandtab shiftwidth=8 tabstop=8: */
778