faudio: Import upstream release 24.05.
[wine.git] / libs / faudio / src / FAudio_internal.h
blob6c7623d82caa5fc67741312511ff0c363d8c6727
1 /* FAudio - XAudio Reimplementation for FNA
3 * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team
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.
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:
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.
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution.
23 * Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
27 #include "FAudio.h"
28 #include "FAPOBase.h"
29 #include <stdarg.h>
31 #ifdef FAUDIO_WIN32_PLATFORM
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <malloc.h>
36 #include <math.h>
37 #include <assert.h>
38 #include <inttypes.h>
40 #define WIN32_LEAN_AND_MEAN
41 #include <windows.h>
43 #define FAudio_malloc malloc
44 #define FAudio_realloc realloc
45 #define FAudio_free free
46 #define FAudio_alloca(x) alloca(x)
47 #define FAudio_dealloca(x) (void)(x)
48 #define FAudio_zero(ptr, size) memset(ptr, '\0', size)
49 #define FAudio_memset(ptr, val, size) memset(ptr, val, size)
50 #define FAudio_memcpy(dst, src, size) memcpy(dst, src, size)
51 #define FAudio_memmove(dst, src, size) memmove(dst, src, size)
52 #define FAudio_memcmp(ptr1, ptr2, size) memcmp(ptr1, ptr2, size)
54 #define FAudio_strlen(ptr) strlen(ptr)
55 #define FAudio_strcmp(str1, str2) strcmp(str1, str2)
56 #define FAudio_strncmp(str1, str2, size) strncmp(str1, str2, size)
57 #define FAudio_strlcpy(ptr1, ptr2, size) lstrcpynA(ptr1, ptr2, size)
59 #define FAudio_pow(x, y) pow(x, y)
60 #define FAudio_log(x) log(x)
61 #define FAudio_log10(x) log10(x)
62 #define FAudio_sin(x) sin(x)
63 #define FAudio_cos(x) cos(x)
64 #define FAudio_tan(x) tan(x)
65 #define FAudio_acos(x) acos(x)
66 #define FAudio_ceil(x) ceil(x)
67 #define FAudio_floor(x) floor(x)
68 #define FAudio_abs(x) abs(x)
69 #define FAudio_ldexp(v, e) ldexp(v, e)
70 #define FAudio_exp(x) exp(x)
72 #define FAudio_cosf(x) cosf(x)
73 #define FAudio_sinf(x) sinf(x)
74 #define FAudio_sqrtf(x) sqrtf(x)
75 #define FAudio_acosf(x) acosf(x)
76 #define FAudio_atan2f(y, x) atan2f(y, x)
77 #define FAudio_fabsf(x) fabsf(x)
79 #define FAudio_qsort qsort
81 #define FAudio_assert assert
82 #define FAudio_snprintf snprintf
83 #define FAudio_vsnprintf vsnprintf
84 #define FAudio_getenv getenv
85 #define FAudio_PRIu64 PRIu64
86 #define FAudio_PRIx64 PRIx64
88 extern void FAudio_Log(char const *msg);
90 /* FIXME: Assuming little-endian! */
91 #define FAudio_swap16LE(x) (x)
92 #define FAudio_swap16BE(x) \
93 ((x >> 8) & 0x00FF) | \
94 ((x << 8) & 0xFF00)
95 #define FAudio_swap32LE(x) (x)
96 #define FAudio_swap32BE(x) \
97 ((x >> 24) & 0x000000FF) | \
98 ((x >> 8) & 0x0000FF00) | \
99 ((x << 8) & 0x00FF0000) | \
100 ((x << 24) & 0xFF000000)
101 #define FAudio_swap64LE(x) (x)
102 #define FAudio_swap64BE(x) \
103 ((x >> 32) & 0x00000000000000FF) | \
104 ((x >> 24) & 0x000000000000FF00) | \
105 ((x >> 16) & 0x0000000000FF0000) | \
106 ((x >> 8) & 0x00000000FF000000) | \
107 ((x << 8) & 0x000000FF00000000) | \
108 ((x << 16) & 0x0000FF0000000000) | \
109 ((x << 24) & 0x00FF000000000000) | \
110 ((x << 32) & 0xFF00000000000000)
111 #else
112 #ifdef FAUDIO_SDL3_PLATFORM
113 #include <SDL3/SDL_stdinc.h>
114 #include <SDL3/SDL_assert.h>
115 #include <SDL3/SDL_endian.h>
116 #include <SDL3/SDL_log.h>
117 #else
118 #include <SDL_stdinc.h>
119 #include <SDL_assert.h>
120 #include <SDL_endian.h>
121 #include <SDL_log.h>
122 #endif
124 #define FAudio_malloc SDL_malloc
125 #define FAudio_realloc SDL_realloc
126 #define FAudio_free SDL_free
127 #define FAudio_alloca(x) SDL_stack_alloc(uint8_t, x)
128 #define FAudio_dealloca(x) SDL_stack_free(x)
129 #define FAudio_zero(ptr, size) SDL_memset(ptr, '\0', size)
130 #define FAudio_memset(ptr, val, size) SDL_memset(ptr, val, size)
131 #define FAudio_memcpy(dst, src, size) SDL_memcpy(dst, src, size)
132 #define FAudio_memmove(dst, src, size) SDL_memmove(dst, src, size)
133 #define FAudio_memcmp(ptr1, ptr2, size) SDL_memcmp(ptr1, ptr2, size)
135 #define FAudio_strlen(ptr) SDL_strlen(ptr)
136 #define FAudio_strcmp(str1, str2) SDL_strcmp(str1, str2)
137 #define FAudio_strncmp(str1, str2, size) SDL_strncmp(str1, str1, size)
138 #define FAudio_strlcpy(ptr1, ptr2, size) SDL_strlcpy(ptr1, ptr2, size)
140 #define FAudio_pow(x, y) SDL_pow(x, y)
141 #define FAudio_log(x) SDL_log(x)
142 #define FAudio_log10(x) SDL_log10(x)
143 #define FAudio_sin(x) SDL_sin(x)
144 #define FAudio_cos(x) SDL_cos(x)
145 #define FAudio_tan(x) SDL_tan(x)
146 #define FAudio_acos(x) SDL_acos(x)
147 #define FAudio_ceil(x) SDL_ceil(x)
148 #define FAudio_floor(x) SDL_floor(x)
149 #define FAudio_abs(x) SDL_abs(x)
150 #define FAudio_ldexp(v, e) SDL_scalbn(v, e)
151 #define FAudio_exp(x) SDL_exp(x)
153 #define FAudio_cosf(x) SDL_cosf(x)
154 #define FAudio_sinf(x) SDL_sinf(x)
155 #define FAudio_sqrtf(x) SDL_sqrtf(x)
156 #define FAudio_acosf(x) SDL_acosf(x)
157 #define FAudio_atan2f(y, x) SDL_atan2f(y, x)
158 #define FAudio_fabsf(x) SDL_fabsf(x)
160 #define FAudio_qsort SDL_qsort
162 #ifdef FAUDIO_LOG_ASSERTIONS
163 #define FAudio_assert(condition) \
165 static uint8_t logged = 0; \
166 if (!(condition) && !logged) \
168 SDL_Log("Assertion failed: %s", #condition); \
169 logged = 1; \
172 #else
173 #define FAudio_assert SDL_assert
174 #endif
175 #define FAudio_snprintf SDL_snprintf
176 #define FAudio_vsnprintf SDL_vsnprintf
177 #define FAudio_Log(msg) SDL_Log("%s", msg)
178 #define FAudio_getenv SDL_getenv
179 #define FAudio_PRIu64 SDL_PRIu64
180 #define FAudio_PRIx64 SDL_PRIx64
182 #define FAudio_swap16LE(x) SDL_SwapLE16(x)
183 #define FAudio_swap16BE(x) SDL_SwapBE16(x)
184 #define FAudio_swap32LE(x) SDL_SwapLE32(x)
185 #define FAudio_swap32BE(x) SDL_SwapBE32(x)
186 #define FAudio_swap64LE(x) SDL_SwapLE64(x)
187 #define FAudio_swap64BE(x) SDL_SwapBE64(x)
188 #endif
190 /* Easy Macros */
191 #define FAudio_min(val1, val2) \
192 (val1 < val2 ? val1 : val2)
193 #define FAudio_max(val1, val2) \
194 (val1 > val2 ? val1 : val2)
195 #define FAudio_clamp(val, min, max) \
196 (val > max ? max : (val < min ? min : val))
198 /* Windows/Visual Studio cruft */
199 #ifdef _WIN32
200 #ifdef __cplusplus
201 /* C++ should have `inline`, but not `restrict` */
202 #define restrict
203 #else
204 #define inline __inline
205 #if defined(_MSC_VER)
206 #if (_MSC_VER >= 1700) /* VS2012+ */
207 #define restrict __restrict
208 #else /* VS2010- */
209 #define restrict
210 #endif
211 #else
212 #define restrict
213 #endif
214 #endif
215 #endif
217 /* C++ does not have restrict (though VS2012+ does have __restrict) */
218 #if defined(__cplusplus) && !defined(restrict)
219 #define restrict
220 #endif
222 /* Alignment macro for gcc/clang/msvc */
223 #if defined(__clang__) || defined(__GNUC__)
224 #define ALIGN(type, boundary) type __attribute__((aligned(boundary)))
225 #elif defined(_MSC_VER)
226 #define ALIGN(type, boundary) __declspec(align(boundary)) type
227 #else
228 #define ALIGN(type, boundary) type
229 #endif
231 /* Threading Types */
233 typedef void* FAudioThread;
234 typedef void* FAudioMutex;
235 typedef int32_t (FAUDIOCALL * FAudioThreadFunc)(void* data);
236 typedef enum FAudioThreadPriority
238 FAUDIO_THREAD_PRIORITY_LOW,
239 FAUDIO_THREAD_PRIORITY_NORMAL,
240 FAUDIO_THREAD_PRIORITY_HIGH,
241 } FAudioThreadPriority;
243 /* Linked Lists */
245 typedef struct LinkedList LinkedList;
246 struct LinkedList
248 void* entry;
249 LinkedList *next;
251 void LinkedList_AddEntry(
252 LinkedList **start,
253 void* toAdd,
254 FAudioMutex lock,
255 FAudioMallocFunc pMalloc
257 void LinkedList_PrependEntry(
258 LinkedList **start,
259 void* toAdd,
260 FAudioMutex lock,
261 FAudioMallocFunc pMalloc
263 void LinkedList_RemoveEntry(
264 LinkedList **start,
265 void* toRemove,
266 FAudioMutex lock,
267 FAudioFreeFunc pFree
270 /* Internal FAudio Types */
272 typedef enum FAudioVoiceType
274 FAUDIO_VOICE_SOURCE,
275 FAUDIO_VOICE_SUBMIX,
276 FAUDIO_VOICE_MASTER
277 } FAudioVoiceType;
279 typedef struct FAudioBufferEntry FAudioBufferEntry;
280 struct FAudioBufferEntry
282 FAudioBuffer buffer;
283 FAudioBufferWMA bufferWMA;
284 FAudioBufferEntry *next;
287 typedef void (FAUDIOCALL * FAudioDecodeCallback)(
288 FAudioVoice *voice,
289 FAudioBuffer *buffer, /* Buffer to decode */
290 float *decodeCache, /* Decode into here */
291 uint32_t samples /* Samples to decode */
294 typedef void (FAUDIOCALL * FAudioResampleCallback)(
295 float *restrict dCache,
296 float *restrict resampleCache,
297 uint64_t *resampleOffset,
298 uint64_t resampleStep,
299 uint64_t toResample,
300 uint8_t channels
303 typedef void (FAUDIOCALL * FAudioMixCallback)(
304 uint32_t toMix,
305 uint32_t srcChans,
306 uint32_t dstChans,
307 float *restrict srcData,
308 float *restrict dstData,
309 float *restrict coefficients
312 typedef float FAudioFilterState[4];
314 /* Operation Sets, original implementation by Tyler Glaiel */
316 typedef struct FAudio_OPERATIONSET_Operation FAudio_OPERATIONSET_Operation;
318 void FAudio_OPERATIONSET_Commit(FAudio *audio, uint32_t OperationSet);
319 void FAudio_OPERATIONSET_CommitAll(FAudio *audio);
320 void FAudio_OPERATIONSET_Execute(FAudio *audio);
322 void FAudio_OPERATIONSET_ClearAll(FAudio *audio);
323 void FAudio_OPERATIONSET_ClearAllForVoice(FAudioVoice *voice);
325 void FAudio_OPERATIONSET_QueueEnableEffect(
326 FAudioVoice *voice,
327 uint32_t EffectIndex,
328 uint32_t OperationSet
330 void FAudio_OPERATIONSET_QueueDisableEffect(
331 FAudioVoice *voice,
332 uint32_t EffectIndex,
333 uint32_t OperationSet
335 void FAudio_OPERATIONSET_QueueSetEffectParameters(
336 FAudioVoice *voice,
337 uint32_t EffectIndex,
338 const void *pParameters,
339 uint32_t ParametersByteSize,
340 uint32_t OperationSet
342 void FAudio_OPERATIONSET_QueueSetFilterParameters(
343 FAudioVoice *voice,
344 const FAudioFilterParametersEXT *pParameters,
345 uint32_t OperationSet
347 void FAudio_OPERATIONSET_QueueSetOutputFilterParameters(
348 FAudioVoice *voice,
349 FAudioVoice *pDestinationVoice,
350 const FAudioFilterParametersEXT *pParameters,
351 uint32_t OperationSet
353 void FAudio_OPERATIONSET_QueueSetVolume(
354 FAudioVoice *voice,
355 float Volume,
356 uint32_t OperationSet
358 void FAudio_OPERATIONSET_QueueSetChannelVolumes(
359 FAudioVoice *voice,
360 uint32_t Channels,
361 const float *pVolumes,
362 uint32_t OperationSet
364 void FAudio_OPERATIONSET_QueueSetOutputMatrix(
365 FAudioVoice *voice,
366 FAudioVoice *pDestinationVoice,
367 uint32_t SourceChannels,
368 uint32_t DestinationChannels,
369 const float *pLevelMatrix,
370 uint32_t OperationSet
372 void FAudio_OPERATIONSET_QueueStart(
373 FAudioSourceVoice *voice,
374 uint32_t Flags,
375 uint32_t OperationSet
377 void FAudio_OPERATIONSET_QueueStop(
378 FAudioSourceVoice *voice,
379 uint32_t Flags,
380 uint32_t OperationSet
382 void FAudio_OPERATIONSET_QueueExitLoop(
383 FAudioSourceVoice *voice,
384 uint32_t OperationSet
386 void FAudio_OPERATIONSET_QueueSetFrequencyRatio(
387 FAudioSourceVoice *voice,
388 float Ratio,
389 uint32_t OperationSet
392 /* Public FAudio Types */
394 struct FAudio
396 uint8_t version;
397 uint8_t active;
398 uint32_t refcount;
399 uint32_t initFlags;
400 uint32_t updateSize;
401 FAudioMasteringVoice *master;
402 LinkedList *sources;
403 LinkedList *submixes;
404 LinkedList *callbacks;
405 FAudioMutex sourceLock;
406 FAudioMutex submixLock;
407 FAudioMutex callbackLock;
408 FAudioMutex operationLock;
409 FAudioWaveFormatExtensible mixFormat;
411 FAudio_OPERATIONSET_Operation *queuedOperations;
412 FAudio_OPERATIONSET_Operation *committedOperations;
414 /* Used to prevent destroying an active voice */
415 FAudioSourceVoice *processingSource;
417 /* Temp storage for processing, interleaved PCM32F */
418 #define EXTRA_DECODE_PADDING 2
419 uint32_t decodeSamples;
420 uint32_t resampleSamples;
421 uint32_t effectChainSamples;
422 float *decodeCache;
423 float *resampleCache;
424 float *effectChainCache;
426 /* Allocator callbacks */
427 FAudioMallocFunc pMalloc;
428 FAudioFreeFunc pFree;
429 FAudioReallocFunc pRealloc;
431 /* EngineProcedureEXT */
432 void *clientEngineUser;
433 FAudioEngineProcedureEXT pClientEngineProc;
435 #ifndef FAUDIO_DISABLE_DEBUGCONFIGURATION
436 /* Debug Information */
437 FAudioDebugConfiguration debug;
438 #endif /* FAUDIO_DISABLE_DEBUGCONFIGURATION */
440 /* Platform opaque pointer */
441 void *platform;
444 struct FAudioVoice
446 FAudio *audio;
447 uint32_t flags;
448 FAudioVoiceType type;
450 FAudioVoiceSends sends;
451 float **sendCoefficients;
452 float **mixCoefficients;
453 FAudioMixCallback *sendMix;
454 FAudioFilterParametersEXT *sendFilter;
455 FAudioFilterState **sendFilterState;
456 struct
458 FAPOBufferFlags state;
459 uint32_t count;
460 FAudioEffectDescriptor *desc;
461 void **parameters;
462 uint32_t *parameterSizes;
463 uint8_t *parameterUpdates;
464 uint8_t *inPlaceProcessing;
465 } effects;
466 FAudioFilterParametersEXT filter;
467 FAudioFilterState *filterState;
468 FAudioMutex sendLock;
469 FAudioMutex effectLock;
470 FAudioMutex filterLock;
472 float volume;
473 float *channelVolume;
474 uint32_t outputChannels;
475 FAudioMutex volumeLock;
477 FAUDIONAMELESS union
479 struct
481 /* Sample storage */
482 uint32_t decodeSamples;
483 uint32_t resampleSamples;
485 /* Resampler */
486 float resampleFreq;
487 uint64_t resampleStep;
488 uint64_t resampleOffset;
489 uint64_t curBufferOffsetDec;
490 uint32_t curBufferOffset;
492 /* WMA decoding */
493 #ifdef HAVE_WMADEC
494 struct FAudioWMADEC *wmadec;
495 #endif /* HAVE_WMADEC*/
497 /* Read-only */
498 float maxFreqRatio;
499 FAudioWaveFormatEx *format;
500 FAudioDecodeCallback decode;
501 FAudioResampleCallback resample;
502 FAudioVoiceCallback *callback;
504 /* Dynamic */
505 uint8_t active;
506 float freqRatio;
507 uint8_t newBuffer;
508 uint64_t totalSamples;
509 FAudioBufferEntry *bufferList;
510 FAudioBufferEntry *flushList;
511 FAudioMutex bufferLock;
512 } src;
513 struct
515 /* Sample storage */
516 uint32_t inputSamples;
517 uint32_t outputSamples;
518 float *inputCache;
519 uint64_t resampleStep;
520 FAudioResampleCallback resample;
522 /* Read-only */
523 uint32_t inputChannels;
524 uint32_t inputSampleRate;
525 uint32_t processingStage;
526 } mix;
527 struct
529 /* Output stream, allocated by Platform */
530 float *output;
532 /* Needed when inputChannels != outputChannels */
533 float *effectCache;
535 /* Read-only */
536 uint32_t inputChannels;
537 uint32_t inputSampleRate;
538 } master;
542 /* Internal Functions */
543 void FAudio_INTERNAL_InsertSubmixSorted(
544 LinkedList **start,
545 FAudioSubmixVoice *toAdd,
546 FAudioMutex lock,
547 FAudioMallocFunc pMalloc
549 void FAudio_INTERNAL_UpdateEngine(FAudio *audio, float *output);
550 void FAudio_INTERNAL_ResizeDecodeCache(FAudio *audio, uint32_t size);
551 void FAudio_INTERNAL_AllocEffectChain(
552 FAudioVoice *voice,
553 const FAudioEffectChain *pEffectChain
555 void FAudio_INTERNAL_FreeEffectChain(FAudioVoice *voice);
556 uint32_t FAudio_INTERNAL_VoiceOutputFrequency(
557 FAudioVoice *voice,
558 const FAudioVoiceSends *pSendList
560 extern const float FAUDIO_INTERNAL_MATRIX_DEFAULTS[8][8][64];
562 /* Debug */
564 #ifdef FAUDIO_DISABLE_DEBUGCONFIGURATION
566 #define LOG_ERROR(engine, fmt, ...)
567 #define LOG_WARNING(engine, fmt, ...)
568 #define LOG_INFO(engine, fmt, ...)
569 #define LOG_DETAIL(engine, fmt, ...)
570 #define LOG_API_ENTER(engine)
571 #define LOG_API_EXIT(engine)
572 #define LOG_FUNC_ENTER(engine)
573 #define LOG_FUNC_EXIT(engine)
574 /* TODO: LOG_TIMING */
575 #define LOG_MUTEX_CREATE(engine, mutex)
576 #define LOG_MUTEX_DESTROY(engine, mutex)
577 #define LOG_MUTEX_LOCK(engine, mutex)
578 #define LOG_MUTEX_UNLOCK(engine, mutex)
579 /* TODO: LOG_MEMORY */
580 /* TODO: LOG_STREAMING */
582 #define LOG_FORMAT(engine, waveFormat)
584 #else
586 #if defined(_MSC_VER)
587 /* VC doesn't support __attribute__ at all, and there's no replacement for format. */
588 void FAudio_INTERNAL_debug(
589 FAudio *audio,
590 const char *file,
591 uint32_t line,
592 const char *func,
593 const char *fmt,
596 #if _MSC_VER <= 1700 /* <=2012 also doesn't support __func__ */
597 #define __func__ __FUNCTION__
598 #endif
599 #else
600 void FAudio_INTERNAL_debug(
601 FAudio *audio,
602 const char *file,
603 uint32_t line,
604 const char *func,
605 const char *fmt,
607 ) __attribute__((format(printf,5,6)));
608 #endif
609 void FAudio_INTERNAL_debug_fmt(
610 FAudio *audio,
611 const char *file,
612 uint32_t line,
613 const char *func,
614 const FAudioWaveFormatEx *fmt
617 #define PRINT_DEBUG(engine, cond, type, fmt, ...) \
618 if (engine->debug.TraceMask & FAUDIO_LOG_##cond) \
620 FAudio_INTERNAL_debug( \
621 engine, \
622 __FILE__, \
623 __LINE__, \
624 __func__, \
625 type ": " fmt, \
626 __VA_ARGS__ \
627 ); \
630 #define LOG_ERROR(engine, fmt, ...) PRINT_DEBUG(engine, ERRORS, "ERROR", fmt, __VA_ARGS__)
631 #define LOG_WARNING(engine, fmt, ...) PRINT_DEBUG(engine, WARNINGS, "WARNING", fmt, __VA_ARGS__)
632 #define LOG_INFO(engine, fmt, ...) PRINT_DEBUG(engine, INFO, "INFO", fmt, __VA_ARGS__)
633 #define LOG_DETAIL(engine, fmt, ...) PRINT_DEBUG(engine, DETAIL, "DETAIL", fmt, __VA_ARGS__)
634 #define LOG_API_ENTER(engine) PRINT_DEBUG(engine, API_CALLS, "API Enter", "%s", __func__)
635 #define LOG_API_EXIT(engine) PRINT_DEBUG(engine, API_CALLS, "API Exit", "%s", __func__)
636 #define LOG_FUNC_ENTER(engine) PRINT_DEBUG(engine, FUNC_CALLS, "FUNC Enter", "%s", __func__)
637 #define LOG_FUNC_EXIT(engine) PRINT_DEBUG(engine, FUNC_CALLS, "FUNC Exit", "%s", __func__)
638 /* TODO: LOG_TIMING */
639 #define LOG_MUTEX_CREATE(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Create", "%p (%s)", mutex, #mutex)
640 #define LOG_MUTEX_DESTROY(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Destroy", "%p (%s)", mutex, #mutex)
641 #define LOG_MUTEX_LOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Lock", "%p (%s)", mutex, #mutex)
642 #define LOG_MUTEX_UNLOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Unlock", "%p (%s)", mutex, #mutex)
643 /* TODO: LOG_MEMORY */
644 /* TODO: LOG_STREAMING */
646 #define LOG_FORMAT(engine, waveFormat) \
647 if (engine->debug.TraceMask & FAUDIO_LOG_INFO) \
649 FAudio_INTERNAL_debug_fmt( \
650 engine, \
651 __FILE__, \
652 __LINE__, \
653 __func__, \
654 waveFormat \
655 ); \
658 #endif /* FAUDIO_DISABLE_DEBUGCONFIGURATION */
660 /* FAPOFX Creators */
662 #define CREATE_FAPOFX_FUNC(effect) \
663 extern uint32_t FAPOFXCreate##effect( \
664 FAPO **pEffect, \
665 const void *pInitData, \
666 uint32_t InitDataByteSize, \
667 FAudioMallocFunc customMalloc, \
668 FAudioFreeFunc customFree, \
669 FAudioReallocFunc customRealloc, \
670 uint8_t legacy \
672 CREATE_FAPOFX_FUNC(EQ)
673 CREATE_FAPOFX_FUNC(MasteringLimiter)
674 CREATE_FAPOFX_FUNC(Reverb)
675 CREATE_FAPOFX_FUNC(Echo)
676 #undef CREATE_FAPOFX_FUNC
678 /* SIMD Stuff */
680 /* Callbacks declared as functions (rather than function pointers) are
681 * scalar-only, for now. SIMD versions should be possible for these.
684 extern void (*FAudio_INTERNAL_Convert_U8_To_F32)(
685 const uint8_t *restrict src,
686 float *restrict dst,
687 uint32_t len
689 extern void (*FAudio_INTERNAL_Convert_S16_To_F32)(
690 const int16_t *restrict src,
691 float *restrict dst,
692 uint32_t len
694 extern void (*FAudio_INTERNAL_Convert_S32_To_F32)(
695 const int32_t *restrict src,
696 float *restrict dst,
697 uint32_t len
700 extern FAudioResampleCallback FAudio_INTERNAL_ResampleMono;
701 extern FAudioResampleCallback FAudio_INTERNAL_ResampleStereo;
702 extern void FAudio_INTERNAL_ResampleGeneric(
703 float *restrict dCache,
704 float *restrict resampleCache,
705 uint64_t *resampleOffset,
706 uint64_t resampleStep,
707 uint64_t toResample,
708 uint8_t channels
711 extern void (*FAudio_INTERNAL_Amplify)(
712 float *output,
713 uint32_t totalSamples,
714 float volume
717 extern FAudioMixCallback FAudio_INTERNAL_Mix_Generic;
719 #define MIX_FUNC(type) \
720 extern void FAudio_INTERNAL_Mix_##type##_Scalar( \
721 uint32_t toMix, \
722 uint32_t srcChans, \
723 uint32_t dstChans, \
724 float *restrict srcData, \
725 float *restrict dstData, \
726 float *restrict coefficients \
728 MIX_FUNC(Generic)
729 MIX_FUNC(1in_1out)
730 MIX_FUNC(1in_2out)
731 MIX_FUNC(1in_6out)
732 MIX_FUNC(1in_8out)
733 MIX_FUNC(2in_1out)
734 MIX_FUNC(2in_2out)
735 MIX_FUNC(2in_6out)
736 MIX_FUNC(2in_8out)
737 #undef MIX_FUNC
739 void FAudio_INTERNAL_InitSIMDFunctions(uint8_t hasSSE2, uint8_t hasNEON);
741 /* Decoders */
743 #define DECODE_FUNC(type) \
744 extern void FAudio_INTERNAL_Decode##type( \
745 FAudioVoice *voice, \
746 FAudioBuffer *buffer, \
747 float *decodeCache, \
748 uint32_t samples \
750 DECODE_FUNC(PCM8)
751 DECODE_FUNC(PCM16)
752 DECODE_FUNC(PCM24)
753 DECODE_FUNC(PCM32)
754 DECODE_FUNC(PCM32F)
755 DECODE_FUNC(MonoMSADPCM)
756 DECODE_FUNC(StereoMSADPCM)
757 DECODE_FUNC(WMAERROR)
758 #undef DECODE_FUNC
760 /* WMA decoding */
762 #ifdef HAVE_WMADEC
763 uint32_t FAudio_WMADEC_init(FAudioSourceVoice *pSourceVoice, uint32_t type);
764 void FAudio_WMADEC_free(FAudioSourceVoice *voice);
765 void FAudio_WMADEC_end_buffer(FAudioSourceVoice *voice);
766 #endif /* HAVE_WMADEC */
768 /* Platform Functions */
770 void FAudio_PlatformAddRef(void);
771 void FAudio_PlatformRelease(void);
772 void FAudio_PlatformInit(
773 FAudio *audio,
774 uint32_t flags,
775 uint32_t deviceIndex,
776 FAudioWaveFormatExtensible *mixFormat,
777 uint32_t *updateSize,
778 void** platformDevice
780 void FAudio_PlatformQuit(void* platformDevice);
782 uint32_t FAudio_PlatformGetDeviceCount(void);
783 uint32_t FAudio_PlatformGetDeviceDetails(
784 uint32_t index,
785 FAudioDeviceDetails *details
788 /* Threading */
790 FAudioThread FAudio_PlatformCreateThread(
791 FAudioThreadFunc func,
792 const char *name,
793 void* data
795 void FAudio_PlatformWaitThread(FAudioThread thread, int32_t *retval);
796 void FAudio_PlatformThreadPriority(FAudioThreadPriority priority);
797 uint64_t FAudio_PlatformGetThreadID(void);
798 FAudioMutex FAudio_PlatformCreateMutex(void);
799 void FAudio_PlatformDestroyMutex(FAudioMutex mutex);
800 void FAudio_PlatformLockMutex(FAudioMutex mutex);
801 void FAudio_PlatformUnlockMutex(FAudioMutex mutex);
802 void FAudio_sleep(uint32_t ms);
804 /* Time */
806 uint32_t FAudio_timems(void);
808 /* WaveFormatExtensible Helpers */
810 static inline uint32_t GetMask(uint16_t channels)
812 if (channels == 1) return SPEAKER_MONO;
813 if (channels == 2) return SPEAKER_STEREO;
814 if (channels == 3) return SPEAKER_2POINT1;
815 if (channels == 4) return SPEAKER_QUAD;
816 if (channels == 5) return SPEAKER_4POINT1;
817 if (channels == 6) return SPEAKER_5POINT1;
818 if (channels == 8) return SPEAKER_7POINT1;
819 FAudio_assert(0 && "Unrecognized speaker layout!");
820 return 0;
823 static inline void WriteWaveFormatExtensible(
824 FAudioWaveFormatExtensible *fmt,
825 int channels,
826 int samplerate,
827 const FAudioGUID *subformat
829 FAudio_assert(fmt != NULL);
830 fmt->Format.wBitsPerSample = 32;
831 fmt->Format.wFormatTag = FAUDIO_FORMAT_EXTENSIBLE;
832 fmt->Format.nChannels = channels;
833 fmt->Format.nSamplesPerSec = samplerate;
834 fmt->Format.nBlockAlign = (
835 fmt->Format.nChannels *
836 (fmt->Format.wBitsPerSample / 8)
838 fmt->Format.nAvgBytesPerSec = (
839 fmt->Format.nSamplesPerSec *
840 fmt->Format.nBlockAlign
842 fmt->Format.cbSize = sizeof(FAudioWaveFormatExtensible) - sizeof(FAudioWaveFormatEx);
843 fmt->Samples.wValidBitsPerSample = 32;
844 fmt->dwChannelMask = GetMask(fmt->Format.nChannels);
845 FAudio_memcpy(&fmt->SubFormat, subformat, sizeof(FAudioGUID));
848 /* Resampling */
850 /* Okay, so here's what all this fixed-point goo is for:
852 * Inevitably you're going to run into weird sample rates,
853 * both from WaveBank data and from pitch shifting changes.
855 * How we deal with this is by calculating a fixed "step"
856 * value that steps from sample to sample at the speed needed
857 * to get the correct output sample rate, and the offset
858 * is stored as separate integer and fraction values.
860 * This allows us to do weird fractional steps between samples,
861 * while at the same time not letting it drift off into death
862 * thanks to floating point madness.
864 * Steps are stored in fixed-point with 32 bits for the fraction:
866 * 00000000000000000000000000000000 00000000000000000000000000000000
867 * ^ Integer block (32) ^ Fraction block (32)
869 * For example, to get 1.5:
870 * 00000000000000000000000000000001 10000000000000000000000000000000
872 * The Integer block works exactly like you'd expect.
873 * The Fraction block is divided by the Integer's "One" value.
874 * So, the above Fraction represented visually...
875 * 1 << 31
876 * -------
877 * 1 << 32
878 * ... which, simplified, is...
879 * 1 << 0
880 * ------
881 * 1 << 1
882 * ... in other words, 1 / 2, or 0.5.
884 #define FIXED_PRECISION 32
885 #define FIXED_ONE (1LL << FIXED_PRECISION)
887 /* Quick way to drop parts */
888 #define FIXED_FRACTION_MASK (FIXED_ONE - 1)
889 #define FIXED_INTEGER_MASK ~FIXED_FRACTION_MASK
891 /* Helper macros to convert fixed to float */
892 #define DOUBLE_TO_FIXED(dbl) \
893 ((uint64_t) (dbl * FIXED_ONE + 0.5))
894 #define FIXED_TO_DOUBLE(fxd) ( \
895 (double) (fxd >> FIXED_PRECISION) + /* Integer part */ \
896 ((fxd & FIXED_FRACTION_MASK) * (1.0 / FIXED_ONE)) /* Fraction part */ \
898 #define FIXED_TO_FLOAT(fxd) ( \
899 (float) (fxd >> FIXED_PRECISION) + /* Integer part */ \
900 ((fxd & FIXED_FRACTION_MASK) * (1.0f / FIXED_ONE)) /* Fraction part */ \
903 #ifdef FAUDIO_DUMP_VOICES
904 /* File writing structure */
905 typedef size_t (FAUDIOCALL * FAudio_writefunc)(
906 void *data,
907 const void *src,
908 size_t size,
909 size_t count
911 typedef size_t (FAUDIOCALL * FAudio_sizefunc)(
912 void *data
914 typedef struct FAudioIOStreamOut
916 void *data;
917 FAudio_readfunc read;
918 FAudio_writefunc write;
919 FAudio_seekfunc seek;
920 FAudio_sizefunc size;
921 FAudio_closefunc close;
922 void *lock;
923 } FAudioIOStreamOut;
925 FAudioIOStreamOut* FAudio_fopen_out(const char *path, const char *mode);
926 void FAudio_close_out(FAudioIOStreamOut *io);
927 #endif /* FAUDIO_DUMP_VOICES */
929 /* vim: set noexpandtab shiftwidth=8 tabstop=8: */