FAudio_internal.h 24 KB

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