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