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